我正在尝试使用三个线程打印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());
}
}
答案 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
我希望我能帮助你,或者至少让你朝着正确的方向前进:) - 超级模糊