3个线程按顺序打印备用值

时间:2013-03-10 13:39:08

标签: java multithreading

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

下面的实现工作正常,第一个线程打印1,4,7而第二个打印2,5,8和第三个打印3,6,9,但问题是序列没有保持,即输出可以像1, 3,2,4,5,7,8,6,9虽然我希望序列被维护为正确的线程shld打印这些值。 一个条件是我不想使用同步。 [仅供学习之用]

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());
                }
            }

        }
    }

}

16 个答案:

答案 0 :(得分:3)

您应首先打印,然后在:

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

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

答案 1 :(得分:2)

下面的代码片段将按顺序打印数字,所有线程将在任务完成后正常终止。 使用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);
       }
     }

答案 2 :(得分:0)

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

答案 3 :(得分:0)

使用Java的 wait(),notify(),notifyall()方法 您还可以查看这些Tutorial这些方法。

希望这有助于解决您的问题。 。 。

此示例的输出如下。

放:1 得到:1
放:2
得到:2
放:3
得到:3
投入:4
得到:4
放:5
得到:5

答案 4 :(得分:0)

这应该有效:

package com.sid;

import java.util.concurrent.atomic.AtomicInteger;

public class NumberSequence {

    private AtomicInteger sharedOutput = new AtomicInteger(0);
    private Object object = new Object();

    public static void main(String args[]) {

        NumberSequence t = new NumberSequence();

        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() < 10) {

                synchronized (object) {

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

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

        }
    }

}

答案 5 :(得分:0)

正确的同步可以帮助您获得明确的答案。我已经改进了实施,你应该解决你的问题。

    int threadId;
    int moduluos;
    int numOfThreads;

    public ThreadTasks(int id, int nubOfThreads) {
        threadId = id;
        this.numOfThreads = nubOfThreads;
        moduluos = threadId%numOfThreads;
    }

    public void run() {
        print();
    }

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

}

答案 6 :(得分:0)

    package test.mk.thread;
import java.util.concurrent.atomic.AtomicInteger;

public class MkThread2 {
    int nextThreadToRun = 1;
    int[] arr = {1,2,3,4,5,6,7,8,9,10,11};
    AtomicInteger nextArrayIndex = new AtomicInteger(0);
    boolean token = true;

    public static void main(String[] args) {
        MkThread2 mkThread = new MkThread2();
        Thread t1 = new Thread(new Worker2(1, mkThread));
        Thread t2 =  new Thread(new Worker2(2, mkThread));
        Thread t3 =  new Thread(new Worker2(3, mkThread));
        t1.start();
        t2.start();
        t3.start();
    }
}


class Worker2 implements Runnable{
    volatile int threadNo;
    private MkThread2 mkThread;
    private String threadName;

    Worker2(int threadNo, MkThread2 mkThread){
        this.threadNo = threadNo;
        this.mkThread = mkThread;
        this.threadName = "Thread:"+threadNo ;
    }

    public void run(){
        try{
            synchronized (mkThread) {
                while(mkThread.token){
                    while(threadNo != mkThread.nextThreadToRun){
                        mkThread.wait();
                    }
                    if(mkThread.token){//double checking
                        System.out.print(threadName+ "->" + mkThread.arr[mkThread.nextArrayIndex.get()]);
                        if(threadNo == 3) System.out.println();
                        mkThread.nextThreadToRun = getNextThread(threadNo);
                        if(mkThread.nextArrayIndex.get() == mkThread.arr.length-1){
                            mkThread.token = false;
                        }
                        mkThread.nextArrayIndex.incrementAndGet();
                    }
                    mkThread.notifyAll();

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

    private int getNextThread(int threadNo){
        int result = -1;
        switch (threadNo) {
        case (1):
            result = 2;
            break;
        case (2):
            result = 3;
            break;
        case (3):
            result = 1;
            break;
        }
        return result;
    }
}

答案 7 :(得分:0)

import java.util.concurrent.atomic.AtomicInteger; 
 public class Print123456789 {

public static void main(String[] args) {
    print p1 = new print(0);
    print p2 = new print(1);
    print p3 = new print(2);

    Thread t1 = new Thread(p1);
    Thread t2 = new Thread(p2);
    Thread t3 = new Thread(p3);

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


}

}



class print implements Runnable {
private int threadNumber;
private static AtomicInteger atomicInteger = new AtomicInteger(0);
public print(int threadNumber) {
    super();
    this.threadNumber = threadNumber;
}

public void run(){
    try{
    while(atomicInteger.get() < 10){
        synchronized (atomicInteger) {

            if((atomicInteger.get()%3) == this.threadNumber){
                System.out.println(atomicInteger.getAndIncrement() + " Thread :" + this.threadNumber );
                atomicInteger.notifyAll();
                }
            else
                atomicInteger.wait();
        }
    }
    }catch(InterruptedException e)
    {
        e.printStackTrace();
    }
}


}

答案 8 :(得分:0)

使用阻塞队列可以更好地实现这一点。定义一个持有阻塞队列的worker。工作人员等待队列,直到它收到一个数字。它打印它接收的数字,递增它并将其传递给链中的下一个工作者。有关完整解决方案,请参阅here

答案 9 :(得分:0)

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();
  }

}

答案 10 :(得分:0)

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

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

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();
                }

            }
        }
    }

}

答案 11 :(得分:0)

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

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();
        }
    }
}

希望这能解决您的问题。

答案 12 :(得分:0)

ThreadSynchronization类可用于在&#39; n&#39;之间打印数字。没有。顺序的线程。 逻辑是在每个连续线程之间创建一个公共对象,并使用“等待”,“通知”#39;按顺序打印数字。 注意:最后一个线程将与第一个线程共享一个对象。

您可以更改&#39; maxThreads&#39;在运行之前增加或减少程序中线程数的值。

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();
        }
    }
}

答案 13 :(得分:0)

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);
        }
     }
    }
}

答案 14 :(得分:0)

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());
            }
        }
    }
}

输出:

  

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

答案 15 :(得分:0)

使用3个线程按顺序打印备用值的任务可以通过使用信号量- 我们将使用3个信号量,然后将它们相互协调以按顺序打印数字

enter image description here

按如下所示创建3个信号灯-

Semaphore one = new Semaphore(1);
Semaphore two = new Semaphore(0);
Semaphore three = new Semaphore(0);

按以下步骤将它们传递给线程-

    PrintOneNumber printOneNumber = new PrintOneNumber(one, two);
    PrintTwoNumber printTwoNumber = new PrintTwoNumber(two, three);
    PrintThreeNumber printThreeNumber = new PrintThreeNumber(three, one);

第一个线程将具有

@Override
public void run() {
    for (int i = 1;; i = i + 3) {
        try {
            sempahoreOne.acquire();
            System.out.println(i);
            sempahoreTwo.release();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

第二个线程将具有

@Override
    public void run() {
        for (int i = 2;; i = i + 3) {
            try {
                sempahoreTwo.acquire();

                Thread.sleep(1000);
                System.out.println(i);
                sempahoreThree.release();
            } catch (InterruptedException e) 
{
                e.printStackTrace();
            }

        }

}

第三个线程将有

@Override
        public void run() {
            for (int i = 3;; i = i + 3) {
                try {
                    sempahoreThree.acquire();

                    Thread.sleep(1000);
                    System.out.println(i);
                    sempahoreOne.release();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }

        }

带有图和源代码的详细说明- Java Semaphore - Print Alternate Numbers Sequence Using Three Threads