繁体   English   中英

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

[英]Using multiple threads to print statements sequentially

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

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

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

我正在尝试创建此示例以供学习。 我在SO上看到过其他页面,也有同样的问题,但是我无法理解这个概念。

任何帮助表示赞赏。

这个例子与我的工作有何不同? 使用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打印由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());
    }


}

请在这里查看我的解决方案。

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

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

对于“与偶数/奇数线程问题有何不同”的查询。 ->几乎是相同的...不必保持两个状态有一个以上的状态来调用第三个线程,所以我相信,这可以扩展为任意数量的线程。

编辑:

当您希望有n个线程按顺序执行工作时,可以查看此方法。(而不是使用不同的类t1,t2,t3等)

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

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

我试图使用单个类'Thrd'进行解决,该类以其起始编号初始化。

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

维护前一个线程状态的状态类。(以保持顺序)

您来了..(请回顾一下,并让我知道您的看法)

编辑:如何工作->

当线程Tx有机会执行时。它将使用x设置状态变量的状态。 因此,一旦状态更新,下一个正在等待的线程(Tx + 1)将有机会。 这样,您可以维护线程的顺序。

我希望我能够解释该代码。 请运行它,并查看或让我知道以下代码中的任何特定查询

1)打包com.kalyan.concurrency;

    public class ThreadConfig {

        public static final int size = 5;

    }

2)打包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)打包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..............

希望我理解的正确,但是Java中有一些主要的“功能”可以使变量在线程之间共享:

  • volatile关键字

    volatile int数量= 1;

  • AtomicInteger (标准Java类->无库)

    AtomicInteger号=新的AtomicInteger(1);

这两种技术都可以满足您的要求,但是我没有使用它的经验,我只是偶然发现了这个词,不知道它是什么意思,并且做了一些挖掘。

一些要阅读的东西:;)

Java的volatile解释-> http://java.dzone.com/articles/java-volatile-keyword-0

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

以及指向AtomicInteger的某些用法的链接-> https://stackoverflow.com/a/4818753/4986655

希望我能为您提供帮助,或者至少向您发送正确的信息:)
-超模糊

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM