[英]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.