使用多个线程按顺序打印语句

时间:2015-06-09 15:11:03

标签: java multithreading concurrency java.util.concurrent

我正在尝试使用三个线程打印1到10之间的数字。线程1打印1,2打印2,3打印3,4再次由线程1打印,依此类推。

我创建了一个共享打印机资源,可帮助这些线程打印数字。但我感到困惑的是,如何让所有线程都能看到这个数字。

问题是每个线程都看到了自己的数字副本,而我需要所有线程共享相同的数字。

我正在尝试创建此示例以用于学习目的。我已经看到SO上的其他页面有同样的问题,但我无法得到这个概念。

感谢任何帮助。

这个例子与我的做法有什么不同? Printing Even and Odd using two Threads in Java

public class PrintAlternateNumber {


    public static void main(String args[]) {

        SharedPrinter printer = new SharedPrinter();

        Thread t1 = new Thread(new myRunnable2(printer,10,1),"1");
        Thread t2 = new Thread(new myRunnable2(printer,10,2),"2");
        Thread t3 = new Thread(new myRunnable2(printer,10,3),"3");

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

class myRunnable2 implements Runnable {

    int max;
    SharedPrinter printer;
    int threadNumber;

    int number=1;

    myRunnable2(SharedPrinter printer,int max,int threadNumber) {
        this.max=max;
        this.printer=printer;
        this.threadNumber=threadNumber;
    }

    @Override
    public void run() {
        System.out.println(" The thread that just entered run "+ Thread.currentThread().getName());     
        for(int i =1;i<max;i++){
            try {
                printer.print(i,threadNumber);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }


}


class SharedPrinter {

    boolean canPrintFlag=false;


    public synchronized void print(int number,int threadNumber) throws InterruptedException{

        if(number%3==threadNumber) {
            canPrintFlag=true;
        }

        while(!canPrintFlag)
        {
            System.out.println(Thread.currentThread().getName() + " is waiting as it cannot print " + number);
            wait();


        }
        System.out.println(Thread.currentThread().getName()+" printed "+number);
        canPrintFlag=false;
        notifyAll();



    }
}

//output
 //The thread that just entered run 2
// The thread that just entered run 3
 //The thread that just entered run 1
//3 is waiting as it cannot print 1
//1 printed 1
//1 is waiting as it cannot print 2
//3 is waiting as it cannot print 1
//2 is waiting as it cannot print 1

技术第二

它仍然不完整,但我很接近

输出

0由0打印 2印刷2 1印刷品

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

class AlternateNumber {

    public static void main(String args[]) {

        printerHell ph = new printerHell();
        BlockingQueue<Integer> queue = new ArrayBlockingQueue<Integer>(10);     
        for(int i=0;i<10;i++)
        {
            queue.add(i);
        }

        Thread t1 = new Thread(new myRunnableHell(queue,0,ph),"0");
        Thread t2 = new Thread(new myRunnableHell(queue,1,ph),"1");
        Thread t3 = new Thread(new myRunnableHell(queue,2,ph),"2");

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

}

class myRunnableHell implements Runnable {

    BlockingQueue<Integer> queue;   
    int threadNumber;
    printerHell ph;

    myRunnableHell(BlockingQueue<Integer> queue, int threadNumber,printerHell ph) {

        this.queue=queue;       
        this.threadNumber=threadNumber;
        this.ph=ph;
    };

    int currentNumber;

    @Override
    public void run() {

        for(int i=0;i<queue.size();i++)
        {
            currentNumber=queue.remove();

            if(threadNumber%3==currentNumber) 
            {
                ph.print(currentNumber);
            }   

        }   

    }   

}

class printerHell {

    public synchronized void print(int Number)
    {
        System.out.println(Number + "printed by" + Thread.currentThread().getName());
    }


}

2 个答案:

答案 0 :(得分:1)

请在此处查看我的解决方案..

使用简单的等待/通知 https://stackoverflow.com/a/31668619/1044396

使用循环障碍: https://stackoverflow.com/a/23752952/1044396

关于'与偶数/奇数线程问题有多么不同的问题。 - &GT;它几乎相同......而不是维持两个状态有一个状态来调用第三个线程,所以我相信,这可以扩展任意数量的线程。

编辑:

当你想要'n'个线程来顺序完成工作时,你可以查看这种方法。(而不是有不同的类t1,t2,t3等)

https://codereview.stackexchange.com/a/98305/78940

EDIT2: 再次在此处复制代码以获得上述解决方案

我尝试使用单个类'Thrd'来解决,它使用其起始编号初始化。

ThreadConfig类,它是您要创建的线程总数的大小。

维护前一个线程状态的状态类(维护排序)

你去..(请查看并告诉我你的意见)

编辑: 它是如何工作的 - &gt;

当线程Tx有机会执行时......它将使用x设置状态变量的状态。所以下一个线程(Tx + 1)等待,一旦状态得到更新就会有机会。这样就可以保持线程的顺序。

我希望我能够解释代码。请运行它并查看或告知我对以下代码的任何具体疑问

1)         包com.kalyan.concurrency;

    public class ThreadConfig {

        public static final int size = 5;

    }

2)package com.kalyan.concurrency;

    public class State {

      private volatile int state ;

        public State() {
            this.state =3;
        }

        public State(int state) {
            this.state = state;
        }

        public  int getState() {
            return state;
        }

        public  void setState(int state) {
            this.state = state;
        }


    }

3)package com.kalyan.concurrency;

        public class Thrd implements Runnable {

            int i ;
            int name;
            int prevThread;
            State s;
            public Thrd(int i,State s) {
                this.i=i;
                this.name=i;
                this.prevThread=i-1;
                if(prevThread == 0) prevThread=ThreadConfig.size;
                this.s=s;
            }

            @Override
            public void run() {


                while(i<50)
                {
                    synchronized(s)
                      {
                          while(s.getState() != prevThread)
                          {


                                  try {
                                    s.wait();
                                } catch (InterruptedException e) {
                                    // TODO Auto-generated catch block
                                    e.printStackTrace();
                                }
                              }

                          } 

                              synchronized(s)
                              {
                               //if(s.getState() ==3)

                              if(s.getState()==prevThread)
                               System.out.println("t"+ name+ i);
                               s.setState(name);
                                   i = i +ThreadConfig.size ;
                              s.notifyAll();


                             }   
                }

            }

        }

4)                     包com.kalyan.concurrency;

        public class T1t2t3 {
        public static void main(String[] args) {

            State s = new State(ThreadConfig.size);


            for(int i=1;i<=ThreadConfig.size;i++)
            {
                Thread T = new Thread(new Thrd(i,s));   
                T.start();

            }



        }
        }

<强>输出:

 t11
 t22
 t33
 t44
 t55
 t16
 t27
 t38
 t49
 t510
 t111
 t212
 t313
 t414
 t515
 t116..............

答案 1 :(得分:-2)

我希望我理解你是正确的,但是在java中有主要的“功能”来使线程之间共享一个变量:

  • volatile 关键字

    volatile int number = 1;

  • AtomicInteger (标准java类 - &gt;无库)

    AtomicInteger number = new AtomicInteger(1);

这两种技术都应该做你想要的,但是我没有使用它的经验,我只是发现了这个词,不知道它意味着什么并做了一些挖掘。

要阅读的内容:;)

java解释的volatile - &gt; http://java.dzone.com/articles/java-volatile-keyword-0

更好的解释(使用IMAGES !!)但是对于c#(仍然是相同的用法) - &gt; http://igoro.com/archive/volatile-keyword-in-c-memory-model-explained/

指向AtomicInteger的一些用法的链接 - &gt; https://stackoverflow.com/a/4818753/4986655

我希望我能帮助你,或者至少让你朝着正确的方向前进:) - 超级模糊