java 3 线程按顺序打印数字

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/30964133/
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-11-02 17:54:19  来源:igfitidea点击:

3 Threads Printing numbers in sequence

javamultithreading

提问by Way2Go

I am trying to write a simple code to print numbers in sequence. Scenario is like

我正在尝试编写一个简单的代码来按顺序打印数字。场景就像

Thread  Number
T1        1
T2        2
T3        3
T1        4
T2        5
T3        6
T1        7
T2        8
T3        9
...and so on.

Here is the

这里是

public class ThreadNumberPrinter {

    Object monitor = new Object();
    AtomicInteger number = new AtomicInteger(1);

    public static void main(String[] args) {
        ThreadNumberPrinter tnp = new ThreadNumberPrinter();
        Thread t1 = new Thread(tnp.new Printer(1, 3));
        Thread t2 = new Thread(tnp.new Printer(2, 3));
        Thread t3 = new Thread(tnp.new Printer(3, 3));

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

    class Printer implements Runnable {

        int threadId;
        int numOfThreads;

        public Printer(int id, int nubOfThreads) {
            threadId = id;
            this.numOfThreads = nubOfThreads;
        }

        public void run() {
            print();
        }

        private void print() {
            try {
                while (true) {
                    Thread.sleep(1000l);
                    synchronized (monitor) {
                        if (number.get() % numOfThreads != threadId) {
                            monitor.wait();
                        } else {
                            System.out.println("ThreadId [" + threadId
                                    + "] printing -->"
                                    + number.getAndIncrement());
                            monitor.notifyAll();
                        }
                    }
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

       }

   }

But just after 2nd thread runs and prints the number 2, all thread get into wait stage and nothing gets printed. I am not sure where I am doing wrong. Any help would be greatly appreciated.

但是就在第二个线程运行并打印数字 2 之后,所有线程都进入等待阶段并且没有打印任何内容。我不确定我哪里做错了。任何帮助将不胜感激。

采纳答案by sodik

Well, the problem is that modulo 3 % 3is 0. Change your threadIds to 0..2instead of 1..3and hopefully it should work.

好吧,问题是模数3 % 30. 将您的threadIds更改为0..2而不是,1..3希望它应该可以工作。

回答by Naresh Joshi

  public class TestClass {

    private volatile Integer count = 1;
    private volatile Integer threadIdToRun = 1;
    private Object object = new Object();

    public static void main(String[] args) {

        TestClass testClass = new TestClass();
        Thread t1 = new Thread(testClass.new Printer(1));
        Thread t2 = new Thread(testClass.new Printer(2));
        Thread t3 = new Thread(testClass.new Printer(3));

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

    class Printer implements Runnable {

        private int threadId;

        public Printer(int threadId) {
            super();
            this.threadId = threadId;
        }

        @Override
        public void run() {
            try {
                while (count <= 20) {
                    synchronized (object) {
                        if (threadId != threadIdToRun) {
                            object.wait();
                        } else {
                            System.out.println("Thread " + threadId + " printed " + count);
                            count += 1;

                            if (threadId == 1)
                                threadIdToRun = 2;
                            else if (threadId == 2)
                                threadIdToRun = 3;
                            else if (threadId == 3)
                                threadIdToRun = 1;

                            object.notifyAll();
                        }
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }

        }
    }
}

Above program gives output

上面的程序给出了输出

Thread 1 printed 1
Thread 2 printed 2
Thread 3 printed 3
Thread 1 printed 4
Thread 2 printed 5
Thread 3 printed 6
Thread 1 printed 7
Thread 2 printed 8
Thread 3 printed 9
Thread 1 printed 10
Thread 2 printed 11
Thread 3 printed 12
Thread 1 printed 13
Thread 2 printed 14
Thread 3 printed 15
Thread 1 printed 16
Thread 2 printed 17
Thread 3 printed 18
Thread 1 printed 19
Thread 2 printed 20

回答by akhil_mittal

Though this is a bad way for using threads, if we still want it a generic solution can be to have a worker thread which will store its id:

虽然这对于使用线程来说是一种糟糕的方式,但如果我们仍然想要它,一个通用的解决方案可以是让一个工作线程来存储它的 id:

class Worker extends Thread {
    private final ResourceLock resourceLock;
    private final int threadNumber;
    private final AtomicInteger counter;
    private volatile boolean running = true;
    public Worker(ResourceLock resourceLock, int threadNumber, AtomicInteger counter) {
        this.resourceLock = resourceLock;
        this.threadNumber = threadNumber;
        this.counter = counter;
    }
    @Override
    public void run() {
        while (running) {
            try {
                synchronized (resourceLock) {
                    while (resourceLock.flag != threadNumber) {
                        resourceLock.wait();
                    }
                    System.out.println("Thread:" + threadNumber + " value: " + counter.incrementAndGet());
                    Thread.sleep(1000);
                    resourceLock.flag = (threadNumber + 1) % resourceLock.threadsCount;
                    resourceLock.notifyAll();
                }
            } catch (Exception e) {
                System.out.println("Exception: " + e);
            }
        }
    }
    public void shutdown() {
        running = false;
    }
}

The ResourceLockclass would store flag and max threads count:

ResourceLock班将存储标志和最大线程数:

class ResourceLock {
    public volatile int flag;
    public final int threadsCount;

    public ResourceLock(int threadsCount) {
        this.flag = 0;
        this.threadsCount = threadsCount;
    }
}

And then main class can use it as below:

然后主类可以如下使用它:

public static void main(String[] args) throws InterruptedException {
        final int threadsCount = 3;
        final ResourceLock lock = new ResourceLock(threadsCount);
        Worker[] threads = new Worker[threadsCount];
        final AtomicInteger counter = new AtomicInteger(0);
        for(int i=0; i<threadsCount; i++) {
            threads[i] = new Worker(lock, i, counter);
            threads[i].start();
        }
        Thread.sleep(10000);
        System.out.println("Will try to shutdown now...");
        for(Worker worker: threads) {
            worker.shutdown();
        }
    }

Here after a certain delay we may like to stop the count and the method shutdown in worker provides this provision.

这里经过一定的延迟后,我们可能想停止计数,而 worker 中的 shutdown 方法提供了这个规定。

回答by s-radix

Below code uses the logic of notifying the next thread to print the number and then incrementing it by 1 and then again notifying the next thread and then go in wait state till some thread notifies it. Eg. T1 first prints the value and then makes boolean "second" true for T2 to print the next number. T2 after printing the number makes boolean "third" true for T3. T3 does the same thing by making boolean "first" true for T1 to print the next number.

下面的代码使用通知下一个线程打印数字然后将其递增 1 然后再次通知下一个线程然后进入等待状态直到某个线程通知它的逻辑。例如。T1 首先打印值,然后使布尔值“second”为真,以便 T2 打印下一个数字。打印数字后的 T2 使 T3 的布尔值“第三”为真。T3 通过为 T1 设置布尔值“first”为真来打印下一个数字来做同样的事情。

T1 -> T2 -> T3 -> T1 -> T2 -> T3 -> ........ and so on.

T1 -> T2 -> T3 -> T1 -> T2 -> T3 -> ........ 等等。

public class Test{
  public static volatile int i = 0;
  public static void main(String[] args) throws InterruptedException {
    Object monitor = new Object();
    Notifier notifier = new Notifier(monitor);
    Thread thread1 = new Thread(notifier, "T1");
    Thread thread2 = new Thread(notifier, "T2");
    Thread thread3 = new Thread(notifier, "T3");
    thread1.start();
    thread2.start();
    thread3.start();
  }
}



class Notifier implements Runnable {

  private Object monitor = null;
  private static int i = 1;
  private static boolean first = true;
  private static boolean second = false;
  private static boolean third = false;

  public Notifier(Object objcurr) {
    this.monitor = objcurr;
  }

  @Override
  public void run() {
    try {
      while (true) {
        synchronized (monitor) {
          String Tname = Thread.currentThread().getName();
          if (first && Tname.equalsIgnoreCase("T1")) {
            print();
            first = false;
            second = true;
            monitor.notifyAll();
            monitor.wait();
          } else if (second && Tname.equalsIgnoreCase("T2")) {
            print();
            second = false;
            third = true;
            monitor.notifyAll();
            monitor.wait();
          } else if (third && Tname.equalsIgnoreCase("T3")) {
            print();
            third = false;
            first = true;
            monitor.notifyAll();
            monitor.wait();
          } else {
            monitor.wait();
          }
        }
        Thread.sleep(1000);
      }
    } catch (Exception e) {
      e.printStackTrace();
    }
  }

  private void print() {
    System.out.println(Thread.currentThread().getName() + " - " + Notifier.i++);
  }

回答by Gopi Krishna

public class PrintThreadsSequentially {

static int number = 1;
static final int PRINT_NUMBERS_UPTO = 20;
static Object lock = new Object();

static class SequentialThread extends Thread {
    int remainder = 0;
    int noOfThreads = 0;

    public SequentialThread(String name, int remainder, int noOfThreads) {
        super(name);
        this.remainder = remainder;
        this.noOfThreads = noOfThreads;
    }

    @Override
    public void run() {
        while (number < PRINT_NUMBERS_UPTO) {
            synchronized (lock) {
                while (number % noOfThreads != remainder) { // wait for numbers other than remainder
                    try {
                        lock.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println(getName() + " value " + number);
                number++;
                lock.notifyAll();
            }
        }
    }
}

public static void main(String[] args) {
    SequentialThread first = new SequentialThread("First Thread", 0, 4);
    SequentialThread second = new SequentialThread("Second Thread", 1, 4);
    SequentialThread third = new SequentialThread("Third Thread", 2, 4);
    SequentialThread fourth = new SequentialThread("Fourth Thread", 3, 4);
    first.start();  second.start();   third.start();  fourth.start();
}

}

}

回答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 RoyalTiger

    package com.sourav.mock.Thread;

    import java.util.concurrent.atomic.AtomicInteger;

    public class ThreeThreadComunication implements Runnable {
        AtomicInteger counter;
        int[] array;
        static final Object mutex = new Object();

        public ThreeThreadComunication(int[] array, AtomicInteger counter){
            this.counter = counter;
            this.array = array;
        }

        @Override
        public void run() {
            int i = 0;
            while(i < array.length){
                synchronized(mutex){
                    if(Integer.parseInt(Thread.currentThread().getName()) == counter.get()){
                        System.out.println(array[i]);
                        if(counter.get() == 3){
                            counter.getAndSet(1);
                        }else{
                            int c = counter.get();
                            counter.getAndSet(++c);
                        }
                        i++;
                    }

                    mutex.notifyAll();
                    try {
                        mutex.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

package com.sourav.mock.Thread;

import java.util.concurrent.atomic.AtomicInteger;

public class ThreeThreadComunicationTest {

    public static void main(String[] args) {

        AtomicInteger counter = new AtomicInteger(1);
        int[] array1 = new int[]{1, 4, 7};
        int[] array2 = new int[]{2, 5, 8};
        int[] array3 = new int[]{3, 6, 9};

        ThreeThreadComunication obj1 = new ThreeThreadComunication(array1, counter);
        ThreeThreadComunication obj2 = new ThreeThreadComunication(array2, counter);
        ThreeThreadComunication obj3 = new ThreeThreadComunication(array3, counter);

        Thread t1 = new Thread(obj1, "1");
        Thread t2 = new Thread(obj2, "2");
        Thread t3 = new Thread(obj3, "3");

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

}

回答by vijayinani

How about this?

这个怎么样?

public class PrintNumbers implements Runnable {

    public static final int NO_OF_THREADS = 3;
    public static final int MAX_DIGIT = 20;
    public static final String THREAD_NAME_PREFIX = "t";

    volatile int current = 1;
    private Object lock = new Object();

    public static void main(String[] args) {
        PrintNumbers printNumbers = new PrintNumbers();
        for (int i = 1; i <= NO_OF_THREADS; i++) {
            new Thread(printNumbers, THREAD_NAME_PREFIX + i).start();
        }
    }

    @Override
    public void run() {
        String printThread;
        while (current < MAX_DIGIT) {
            synchronized (lock) {
                if (current % NO_OF_THREADS != 0) {
                    printThread = THREAD_NAME_PREFIX + current % NO_OF_THREADS;
                } else {
                    printThread = THREAD_NAME_PREFIX + NO_OF_THREADS;
                }

                if (!printThread.equals(Thread.currentThread().getName())) {
                    try {
                        lock.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }

                if (printThread.equals(Thread.currentThread().getName())) {
                    System.out.println(String.format("Thread %s : %s", Thread.currentThread().getName(), current));
                    current = current + 1;
                }

                lock.notifyAll();
            }
        }
    }
}

回答by Dnyanesh

I have tried it below simple way to print in sequence using three threads and it is working well.

我已经尝试过使用三个线程按顺序打印的简单方法,并且运行良好。

public class AppPrint123 {

    static int count = 1;
    static int counter = 1;
    static Object lock = new Object();

    public static void main(String[] args) {

        Thread t1 = new Thread(new Runnable() {

            public void run() {
                while (true) {
                    synchronized (lock) {

                        try {
                            Thread.sleep(100);
                            while (count != 1) {
                                lock.wait();
                            }
                            System.out.println(Thread.currentThread().getName() + ": " + counter);
                            count++;
                            counter++;
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        lock.notifyAll();
                    }
                }

            }

        }, "T1");

        Thread t2 = new Thread(new Runnable() {

            public void run() {
                while (true) {
                    synchronized (lock) {

                        try {
                            Thread.sleep(100);
                            while (count != 2) {
                                lock.wait();
                            }
                            System.out.println(Thread.currentThread().getName() + ": " + counter);
                            counter++;
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        lock.notifyAll();
                    }
                }
            }

        }, "T2");

        Thread t3 = new Thread(new Runnable() {

            public void run() {
                while (true) {
                    synchronized (lock) {
                        try {
                            Thread.sleep(100);
                            while (count != 3) {
                                lock.wait();
                            }
                            System.out.println(Thread.currentThread().getName() + ": " + counter);
                            count = count - 2;
                            counter++;
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        lock.notifyAll();
                    }
                }
            }

        }, "T3");

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

    }
}

You can print countvariable instead if you want to generate output like 123123123 in sequence using three threads.

如果要使用三个线程按顺序生成 123123123 之类的输出,则可以改为打印计数变量。

回答by secret super star

Bad way to do but ask is to implement using multiple threads:

不好的方法是使用多个线程来实现:

private static AtomicInteger currentThreadNo = new AtomicInteger(0);
    private static int currentNo = 1;
    private static final Object lock = new Object();

Above, these values are staticso that they remain same for all the worker objects.

上面,这些值static使它们对于所有工作对象保持相同。

import java.util.concurrent.atomic.AtomicInteger;

public class PrintNumbersUsingNThreads implements Runnable {

    private final int threadNo;
    private final int totalThreads;
    private static AtomicInteger currentThreadNo = new AtomicInteger(0);
    private static int currentNo = 1;
    private static final Object lock = new Object();


    public PrintNumbersUsingNThreads(int threadNo, int totalThreads) {
        this.threadNo = threadNo;
        this.totalThreads = totalThreads;
    }

    @Override
    public  void run() {



        while (true) {
            while (currentThreadNo.get() % totalThreads != threadNo) {
                try {

                    synchronized (lock) {
                        lock.wait();
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println(Thread.currentThread().getName() + " printing " + currentNo);
            currentNo++;

            int curr = currentThreadNo.get();
            if (curr == totalThreads) {
                currentThreadNo.set(1);
            } else {
               currentThreadNo.incrementAndGet();
            }
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            synchronized (lock) {
                lock.notifyAll();
            }
        }

    }

    public static void main(String[] args) {
        int totalThreads = 3;

        for(int i = 0; i < totalThreads; i++){
            new Thread(new PrintNumbersUsingNThreads(i,totalThreads),"thread"+i).start();
        }

    }
}

output:

输出:

thread0 printing 1
thread1 printing 2
thread2 printing 3
thread0 printing 4
thread1 printing 5
thread2 printing 6
thread0 printing 7
thread1 printing 8
thread2 printing 9
thread0 printing 10
thread1 printing 11
thread2 printing 12
thread0 printing 13
thread1 printing 14
thread2 printing 15
thread0 printing 16
thread1 printing 17
thread2 printing 18