java 3 个线程按顺序打印替代值

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15322847/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 19:14:09  来源:igfitidea点击:

3 threads to print alternate values in sequence

javamultithreading

提问by Lokesh

I am trying to create an implementation where multiple threads print alternate values of sequence. So here thread1 will print 1,4,7 thread2 will print 2,5,8 thread3 will print 3,6,9. I am using Atomic integer and modulo function.

我正在尝试创建一个实现,其中多个线程打印序列的替代值。所以这里 thread1 会打印 1,4,7 thread2 会打印 2,5,8 thread3 会打印 3,6,9。我正在使用原子整数和模函数。

Below implementation works fine in the sense that first thread prints 1,4,7 while second prints 2,5,8 and third prints 3,6,9 but problem is that sequence is not maintained i.e output can be like 1,3,2,4,5,7,8,6,9 while i want sequence to be maintained as proper threads shld print those values. One condition is i don't want to use synchronize. [Just for learning purpose]

下面的实现在第一个线程打印 1,4,7 而第二个打印 2,5,8 和第三个打印 3,6,9 的意义上工作正常,但问题是没有维护序列,即输出可以像 1,3,2 ,4,5,7,8,6,9 而我希望保持顺序,因为适当的线程应该打印这些值。一个条件是我不想使用同步。【仅供学习】

import java.util.concurrent.atomic.AtomicInteger;

public class ThreeThreadsOrderedLockLess {

    AtomicInteger sharedOutput = new AtomicInteger(0);

    public static void main(String args[]) {



        ThreeThreadsOrderedLockLess t = new ThreeThreadsOrderedLockLess();



        ThreadTasks t1 = t.new ThreadTasks(0);
        ThreadTasks t2 = t.new ThreadTasks(1);
        ThreadTasks t3 = t.new ThreadTasks(2);

        Thread ts1 = new Thread(t1);
        Thread ts2 = new Thread(t2);
        Thread ts3 = new Thread(t3);
        ts1.start();
        ts2.start();
        ts3.start();

    }

    private class ThreadTasks implements Runnable {

        private final int threadPosition;


        public ThreadTasks(int threadPosition) {
            super();

            this.threadPosition = threadPosition;
        }

        @Override
        public void run() {

            while (sharedOutput.get() < 9) {

                if (sharedOutput.get() % 3 == this.threadPosition) {

                    System.out.println("Printing output for Thread: "
                            + this.threadPosition + "  "
                            + sharedOutput.incrementAndGet());
                }
            }

        }
    }

}

回答by JB Nizet

You should print first, and increment after:

您应该先打印,然后再增加:

int value = sharedOutput.get() + 1;
System.out.println("Printing output for Thread: "
                        + this.threadPosition + "  "
                        + value);
sharedOutput.incrementAndGet();

That said, all the threads are busy looping, which will lead to 100% CPU usage. You should synchronize the threads instead.

也就是说,所有线程都忙于循环,这将导致 100% 的 CPU 使用率。您应该改为同步线程。

回答by Gopinath

Below code snippet will print numbers in sequence and all threads will be terminated gracefully after the task. Used AtomicInteger, which is thread-safe for printing the numbers and same logic can be applied to print as till any number with any number of threads.

下面的代码片段将按顺序打印数字,并且所有线程将在任务完成后正常终止。使用 AtomicInteger,它对于打印数字是线程安全的,并且可以应用相同的逻辑来打印具有任意数量线程的任意数字。

 
    import java.util.concurrent.atomic.AtomicInteger;

    public class PrintNumSequence
    {
        public static void main(String[] args)
        {
          AtomicInteger atomicInteger = new AtomicInteger(0);
          new NumPrinter(atomicInteger, 0).start();// thread0
          new NumPrinter(atomicInteger, 1).start();// thread1
          new NumPrinter(atomicInteger, 2).start();// thread2

        }
    }

    class NumPrinter extends Thread
    {

        private AtomicInteger   atomicInteger;
        private int             threadNum;

       public NumPrinter(AtomicInteger atomicInteger, int threadNum)
       {
        this.atomicInteger = atomicInteger;
        this.threadNum = threadNum;
       }

       @Override
       public void run()
       {
        int num = atomicInteger.intValue();
        do
        {
            synchronized (atomicInteger)
            {
                num = atomicInteger.intValue();
                // If number is 9 then stop.
                if (num > 9)
                {
                    atomicInteger.notifyAll();
                    break;
                }
                // 3 is number of threads
                if ((num % 3) == threadNum)
                {
                    System.out.println("Thread-" + threadNum + " -->" + num);
                    num = atomicInteger.incrementAndGet();

                }
                atomicInteger.notifyAll();
                try
                {
                    atomicInteger.wait();
                }
                catch (InterruptedException e)
                {
                    e.printStackTrace();
                }
            }
         } while (true);
       }
     }

回答by giorashc

This is because the time slice for each thread is determined by the OS. So it is possible that thread x increments the shared number but before printing the time slice is passed to the next thread y which now reads the shared number and prints it after incrementing (assuming that thread y got more time than thread x to increament and print the shared number) .

这是因为每个线程的时间片是由操作系统决定的。因此,线程 x 有可能增加共享数,但在打印时间片之前传递给下一个线程 y,该线程现在读取共享数并在递增后打印它(假设线程 y 比线程 x 有更多的时间来增加和打印)共享号码)。

回答by arora

package threeThread;

class Task implements Runnable {

  String message;
  ThreeThread lock;
  int i = 0;
  int p;

  public Task(String text, ThreeThread obj, int p) {
    message = text;
    this.lock = obj;
    this.p = p;
  }

  @Override
  public void run() {

    while(true) {
        synchronized (lock) {

            while(!((lock.status % 3) == 0) && p == 1){
                try {
                    lock.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

            while(!((lock.status % 3) == 1) && p == 2){
                try {
                    lock.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

            while(!((lock.status % 3) == 2) && p == 3){
                try {
                    lock.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("thread: " + p + " : " + message);
            lock.status++;
            lock.notifyAll();
        }
    }
  }
}

public class ThreeThread {

  volatile int status = 0;
  public static void main(String[] args) {

    ThreeThread lock = new ThreeThread();
    Thread t1 = new Thread(new Task("Hello", lock,1));
    Thread t2 = new Thread(new Task("Good", lock,2));
    Thread t3 = new Thread(new Task("Morning", lock,3));
    t1.start();
    t2.start();
    t3.start();
  }

}

回答by Nitin

I am putting code to print 1-100 using 5 threads. One can use any number of thread to print output in round robin fashion.

我正在放置代码以使用 5 个线程打印 1-100。可以使用任意数量的线程以循环方式打印输出。

Basic concept is to lock one object and notify other for executing the printing of value.

基本概念是锁定一个对象并通知另一个对象执行值的打印。

public class PrintOneToHundredUsing5Threads {

    public static void main(String[] args) {
        List<Object> objList = new ArrayList<>();
        for (int i = 0; i < 5; i++) {
            objList.add(new Object());
        }
        for (int i = 0; i < 5; i++) {
            Thread t = new Thread(new PrintThread(objList.get(i), objList.get((i + 1) % 5)));
            t.setName("Thread" + i);
            t.start();
        }
    }

}

class PrintThread implements Runnable {
    Object current;
    Object next;
    volatile static int i = 1;

    PrintThread(Object cur, Object next) {
        this.current = cur;
        this.next = next;
    }

    @Override
    public void run() {
        for (; i <= 100;) {
            synchronized (current) {
                synchronized (next) {
                    next.notify();
                    System.out.println(Thread.currentThread().getName() + " Value : " + i++);
                }
                try {
                    current.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
        }
    }

}

回答by Nilesh N

You can use below code to print sequential numbers using multiple threads -

您可以使用以下代码使用多个线程打印序列号 -

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

public class ThreadCall extends Thread {

    private BlockingQueue<Integer> bq = new ArrayBlockingQueue<Integer>(10);
    private ThreadCall next;

    public void setNext(ThreadCall t) {
        this.next = t;
    }

    public void addElBQ(int a) {
        this.bq.add(a);
    }

    public ThreadCall(String name) {
        this.setName(name);
    }

    @Override
    public void run() {
        int x = 0;
        while(true) {
            try {
                x = 0;
                x = bq.take();
                if (x!=0) {
                    System.out.println(Thread.currentThread().getName() + " =>" + x);
                    if (x >= 100) System.exit(0); // Need to stop all running threads
                    next.addElBQ(x+1);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        int THREAD_COUNT = 10;
        List<ThreadCall> listThread = new ArrayList<>();

        for (int i=1; i<=THREAD_COUNT; i++) {
            listThread.add(new ThreadCall("Thread " + i));
        }

        for (int i = 0; i < listThread.size(); i++) {
            if (i == listThread.size()-1) {
                listThread.get(i).setNext(listThread.get(0));
            }
            else listThread.get(i).setNext(listThread.get(i+1));
        }

        listThread.get(0).addElBQ(1);

        for (int i = 0; i < listThread.size(); i++) {
            listThread.get(i).start();
        }
    }
}

Hope this will resolve your problem.

希望这能解决您的问题。

回答by s-radix

The ThreadSynchronization class can be used to print numbers between 'n' no. of threads in sequence. The logic is to create a common object between each of the consecutive threads and use 'wait', 'notify' to print the numbers in sequence. Note: Last thread will share an object with the first thread.

ThreadSynchronization 类可用于打印“n”号之间的数字。的线程顺序。逻辑是在每个连续线程之间创建一个公共对象,并使用 'wait'、'notify' 依次打印数字。注意:最后一个线程将与第一个线程共享一个对象。

You can change the 'maxThreads' value to increase or decrease the number of thread in the program before running it.

在运行程序之前,您可以更改“maxThreads”值以增加或减少程序中的线程数。

import java.util.ArrayList;
import java.util.List;

public class ThreadSynchronization {

    public static int i = 1;
    public static final int maxThreads = 10;

    public static void main(String[] args) {
        List<Object> list = new ArrayList<>();
        for (int i = 0; i < maxThreads; i++) {
            list.add(new Object());
        }
        Object currObject = list.get(maxThreads - 1);
        for (int i = 0; i < maxThreads; i++) {
            Object nextObject = list.get(i);
            RunnableClass1 a = new RunnableClass1(currObject, nextObject, i == 0 ? true : false);
            Thread th = new Thread(a);
            th.setName("Thread - " + (i + 1));
            th.start();
            currObject = list.get(i);
        }
    }

}

class RunnableClass implements Runnable {

    private Object currObject;
    private Object nextObject;
    private boolean firstThread;

    public RunnableClass(Object currObject, Object nextObject, boolean first) {
        this.currObject = currObject;
        this.nextObject = nextObject;
        this.firstThread = first;
    }

    @Override
    public void run() {
        int i = 0;
        try {
            if (firstThread) {
                Thread.sleep(5000);
                firstThread = false;
                System.out.println(Thread.currentThread().getName() + " - " + ThreadSynchronization.i++);
                synchronized (nextObject) {
                    nextObject.notify();
                }
            }
            while (i++ < Integer.MAX_VALUE) {
                synchronized (currObject) {
                    currObject.wait();
                }
                System.out.println(Thread.currentThread().getName() + " - " + ThreadSynchronization.i++);
                Thread.sleep(1000);
                synchronized (nextObject) {
                    nextObject.notify();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

回答by Ashutosh

public class PrintThreadsInSerial {
    public static void main(String[] args) {
    Thread t = new Thread(new Job());
    t.start();
    }
}

class Job implements Runnable {
    @Override
    public void run() {
     while (true) {
        for (int i = 1; i <= 3; i++) {
         System.out.println(i);
        }
     }
    }
}

回答by Aviral Sharad Srivastava

public class PrintSeqNumUsingAltThreads {

    public static void main(String[] args) {
        AtomicInteger counter = new AtomicInteger(0);
        int numThreads = 3;

        Thread t1 = new Thread(new SeqNumPrinter(counter, 0, numThreads));
        Thread t2 = new Thread(new SeqNumPrinter(counter, 1, numThreads));
        Thread t3 = new Thread(new SeqNumPrinter(counter, 2, numThreads));

        t1.currentThread().setName("T1");
        t2.currentThread().setName("T2");
        t3.currentThread().setName("T3");

        t1.start();
        t2.start();
        t3.start();
    }
}


public class SeqNumPrinter implements Runnable {

    AtomicInteger atmCounter;
    Integer threadPosition;
    Integer numThreads;

    public SeqNumPrinter(AtomicInteger counter, int position, int numThreads) {
        this.atmCounter = counter;
        this.threadPosition = position;
        this.numThreads = numThreads;
    }

    @Override
    public void run() {
        while (atmCounter.get() < 10) {
            if (atmCounter.get() % numThreads == threadPosition) {
                System.out.println("Printing value : " + atmCounter.getAndIncrement() + ", by thread : " + 
                        Thread.currentThread().getName());
            }
        }
    }
}

Output :

输出 :

Printing value : 0, by thread : Thread-0
Printing value : 1, by thread : Thread-1
Printing value : 3, by thread : Thread-0
Printing value : 2, by thread : Thread-2
Printing value : 4, by thread : Thread-1
Printing value : 6, by thread : Thread-0
Printing value : 5, by thread : Thread-2
Printing value : 7, by thread : Thread-1
Printing value : 9, by thread : Thread-0
Printing value : 8, by thread : Thread-2

打印值:0,按线程:Thread-0
打印值:1,按线程:Thread-1
打印值:3,按线程:Thread-0
打印值:2,按线程:Thread-2
打印值:4,按thread : Thread-1
打印值: 6, by thread : Thread-0
打印值: 5, by thread : Thread-2
打印值: 7, by thread : Thread-1
打印值: 9, by thread : Thread-0
打印值:8,按线程:线程 2

回答by adeel iqbal

use wait(), notify(), notifyall()methods of the Java.
you can also take a look at this Tutorialof these methods.

使用Java 的wait()、notify()、notifyall()方法。
你也可以看看这些方法的这个教程

Hope this would be helpful to solve your issue. . .

希望这对解决您的问题有所帮助。. .

the output of this example is as under.

这个例子的输出如下。

Put: 1
Got: 1
Put: 2
Got: 2
Put: 3
Got: 3
Put: 4
Got: 4
Put: 5
Got: 5

放:1
GOT:1
穿戴:2
GOT:2
穿戴:3
GOT:3
穿戴:4
GOT:4
穿戴:5
GOT:5