用3个线程连续打印1、2、3,使用单个可运行不起作用



我想通过线程-1打印1, 2 通过线程-2, 3 通过线程-3 比如123123123等等

我想只使用一个由多个线程共享的可运行对象来实现这一点 从本质上讲,我尝试过的方式是 使用一个原子整数作为信号来指示哪个应该打印 并使用等待和通知在线程之间转移控制权并具有 使用线程名称检查以允许打印特定线程

我已经像下面这样尝试过,它不起作用,有人可以帮助我。

/** Main class which creates 3 threads using one runnable and 
starts the 3 threads */ 
package PrintOneTwoThree;
public class MainClass
{
public static void main(String args[])
{
//one runnable is created and shared by 3 threads
final PrintNumbersConsecutively printRunnable = new 
PrintNumbersConsecutively();
Thread t1 = new Thread(printRunnable, "Thread1");
Thread t2 = new Thread(printRunnable,"Thread2");
Thread t3 = new Thread(printRunnable,"Thread3");
t1.start();
t2.start();
t3.start();
}
}
/** Each of the three threads are made to print 1 ,2 and 3 */
package PrintOneTwoThree;
import java.util.concurrent.atomic.AtomicInteger;
public class PrintNumbersConsecutively implements Runnable
{
private Object monitor = new Object();
AtomicInteger atomicInt = new AtomicInteger(1);
@Override
public void run()
{
System.out.println(Thread.currentThread().getName()+"Started");
// TODO Auto-generated method stub
printNumbers();
}
// method to print the numbers using 3 different threads 1 ,2 and 3
public void printNumbers()
{
try
{
while(true)
{
synchronized (monitor) 
{
System.out.println(Thread.currentThread().getName()+"held 
the lock of monitor");
System.out.println("printVal is"+ atomicInt);
//Thread1 should print 1
if(atomicInt.get() == 1 && 
Thread.currentThread().getName().equals("Thread1"))
{
//prints 1 and next awakes second thread by setting
// atomic int to 2
System.out.println(1);
atomicInt.set(2);
monitor.notifyAll();
System.out.println(Thread.currentThread().getName()+"Releasing 
the lock of monitor");
monitor.wait();
}
//Thread 2 should print 2
if(atomicInt.get() == 2 && 
Thread.currentThread().getName().equals("Thread2"))
{
//prints 2 and next awakes third thread by setting
// atomic int to 3
System.out.println(2);
atomicInt.set(3);
monitor.notifyAll();
monitor.wait();
}
//Thread 3 should print 3
if(atomicInt.get() == 3 && 
Thread.currentThread().getName().equals("Thread3"))
{
//prints 3 and next awakes first thread by setting
// atomic int to 1
System.out.println(3);
atomicInt.set(1);
monitor.notifyAll();
monitor.wait();
}
}
}
}
catch(InterruptedException e)
{
//catches the interrupted excpeiton
}
}
}

输出为

printVal is1 线程2按住显示器的锁 printVal is1 线程2按住显示器的锁 printVal is1 线程2按住显示器的锁 printVal is1 线程2按住显示器的锁 printVal is1 线程2按住显示器的锁 printVal is1 线程2按住显示器的锁 printVal is1 线程2按住显示器的锁 printVal is1 线程2按住显示器的锁 printVal is1 线程2按住显示器的锁 printVal is1 线程2按住显示器的锁 printVal is1 线程2按住显示器的锁 printVal is1 线程2按住显示器的锁 printVal is1 线程2按住显示器的锁 printVal is1 线程2按住显示器的锁 printVal is1 线程2按住显示器的锁 printVal is1 线程2按住显示器的锁 printVal is1 线程2按住显示器的锁 printVal is1 线程2按住显示器的锁 printVal is1 线程2按住显示器的锁 printVal is1 线程2按住显示器的锁 printVal is1 线程2按住显示器的锁 printVal is1 线程2按住显示器的锁

使用以下代码可以实现相同的目的。在这里,我们不使用任何 Atomic 类,而是使用一个简单的监视器对象obj和一个计数器变量count

class T3 {
public Object obj = new Object();
private int MAX = 100;
int count = 1, value = -1;
public void process1() {
while (true) {
if (count > MAX) break;
synchronized (obj) {
if (value == -1) {
System.out.println(Thread.currentThread().getName() + " : " + count++);
value = 0;
obj.notifyAll();
try {
obj.wait();
} catch (InterruptedException e) { }
}
}
}
}
public void process2() {
while (true) {
if (count > MAX) break;
synchronized (obj) {
if (value == 0) {
System.out.println(Thread.currentThread().getName() + " : " + count++);
value = 1;
obj.notifyAll();
try {
obj.wait();
} catch (InterruptedException e) { }
}
}
}
}
public void process3() {
while (true) {
if (count > MAX) break;
synchronized (obj) {
if (value == 1) {
System.out.println(Thread.currentThread().getName() + " : " + count++);
value = -1;
obj.notifyAll();
try {
obj.wait();
} catch (InterruptedException e) { }
}
}
}
}
}

我在代码中进行了以下更改

  • 添加等待
  • 更改如果条件

    public class Practice {
    public static void main(String args[])
    {
    //one runnable is created and shared by 3 threads
    final PrintNumbersConsecutively printRunnable = new
    PrintNumbersConsecutively();
    Thread t1 = new Thread(printRunnable, "Thread1");
    Thread t2 = new Thread(printRunnable,"Thread2");
    Thread t3 = new Thread(printRunnable,"Thread3");
    t1.start();
    t2.start();
    t3.start();
    }
    }
    /** Each of the three threads are made to print 1 ,2 and 3 */
    class PrintNumbersConsecutively implements Runnable
    {
    private Object monitor = new Object();
    AtomicInteger atomicInt = new AtomicInteger(1);
    static boolean one = true;
    static boolean two = false;
    static boolean three = false;
    @Override
    public void run()
    {
    System.out.println(Thread.currentThread().getName()+"Started");
    printNumbers();
    }
    // method to print the numbers using 3 different threads 1 ,2 and 3
    public void printNumbers()
    {
    try
    {
    int i =0;
    while(i < 30)
    {
    synchronized (monitor)
    {
    /*System.out.println(Thread.currentThread().getName()+" held the lock of monitor");
    System.out.println("printVal is"+ atomicInt);*/
    //Thread1 should print 1
    if(Thread.currentThread().getName().equals("Thread1")) {
    if (atomicInt.get() == 1) {
    //prints 1 and next awakes second thread by setting
    // atomic int to 2
    System.out.print(1 + " ");
    atomicInt.set(2);
    monitor.notifyAll();
    // System.out.println(Thread.currentThread().getName() + "Releasing the lock of monitor");
    } else {
    monitor.wait();
    }
    }
    if(Thread.currentThread().getName().equals("Thread2")) {
    if (atomicInt.get() == 2) {
    //prints 1 and next awakes second thread by setting
    // atomic int to 2
    System.out.print(2 + " ");
    atomicInt.set(3);
    monitor.notifyAll();
    //  System.out.println(Thread.currentThread().getName() + "Releasing the lock of monitor");
    } else {
    monitor.wait();
    }
    }
    if(Thread.currentThread().getName().equals("Thread3")) {
    if (atomicInt.get() == 3) {
    //prints 1 and next awakes second thread by setting
    // atomic int to 2
    System.out.print(3 + " ");
    atomicInt.set(1);
    monitor.notifyAll();
    //System.out.println(Thread.currentThread().getName() + "Releasing the lock of monitor");
    } else {
    monitor.wait();
    }
    }
    }
    i++;
    }
    }
    catch(InterruptedException e)
    {
    //catches the interrupted excpeiton
    }
    }
    

    }

输出:

Thread3Started
Thread1Started
Thread2Started
1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 

如果轮不到线程,则应等待。

public void printNumbers()
{
try
{
while(true)
{
synchronized (monitor) 
{
System.out.println(Thread.currentThread().getName()+"held the lock of monitor");
System.out.println("printVal is"+ atomicInt);
//Thread1 should print 1
if(atomicInt.get() == 1 && 
Thread.currentThread().getName().equals("Thread1"))
{
//prints 1 and next awakes second thread by setting
// atomic int to 2
System.out.println(1);
atomicInt.set(2);
monitor.notifyAll();
System.out.println(Thread.currentThread().getName()+"Releasing the lock of monitor");
}
//Thread 2 should print 2
if(atomicInt.get() == 2 && 
Thread.currentThread().getName().equals("Thread2"))
{
//prints 2 and next awakes third thread by setting
// atomic int to 3
System.out.println(2);
atomicInt.set(3);
monitor.notifyAll();
}
//Thread 3 should print 3
if(atomicInt.get() == 3 && 
Thread.currentThread().getName().equals("Thread3"))
{
//prints 3 and next awakes first thread by setting
// atomic int to 1
System.out.println(3);
atomicInt.set(1);
monitor.notifyAll();
}
monitor.wait();
}
}
}
catch(InterruptedException e)
{
//catches the interrupted excpeiton
}
}

代码的微小变化是将所有monitor.wait((if {}部分移动,

synchronized (monitor) {
if() {
....
}
if() {
....
}
if() {
....
}
monitor.wait()
}

我尝试了您的代码并测试了输出,我以您打印的方式获得输出,所以我只是打乱了打印消息,因为它不是以复杂的方式打印的,所以我再次测试了输出它正在以您想要的方式打印。我认为代码中没有任何问题。请尝试此代码。

public class MainClass {
public static void main(String args[]) {
// one runnable is created and shared by 3 threads
final PrintNumbersConsecutively printRunnable = new PrintNumbersConsecutively();
Thread t1 = new Thread(printRunnable, "Thread1");
Thread t2 = new Thread(printRunnable, "Thread2");
Thread t3 = new Thread(printRunnable, "Thread3");
t1.start();
t2.start();
t3.start();
}
}
import java.util.concurrent.atomic.AtomicInteger;
public class PrintNumbersConsecutively implements Runnable {
private Object  monitor     = new Object();
AtomicInteger   atomicInt   = new AtomicInteger(1);
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "Started");
// TODO Auto-generated method stub
printNumbers();
}
// method to print the numbers using 3 different threads 1 ,2 and 3
public void printNumbers() {
try {
while (true) {
synchronized (monitor) {
// Thread1 should print 1
if (atomicInt.get() == 1 && Thread.currentThread().getName().equals("Thread1")) {
// prints 1 and next awakes second thread by setting
// atomic int to 2
atomicInt.set(2);
System.out.println(1);
System.out.println(Thread.currentThread().getName() + "Releasing the lock of monitor");
monitor.notifyAll();
monitor.wait();
}
// Thread 2 should print 2
if (atomicInt.get() == 2 && Thread.currentThread().getName().equals("Thread2")) {
// prints 2 and next awakes third thread by setting
// atomic int to 3
atomicInt.set(3);
System.out.println(2);
System.out.println(Thread.currentThread().getName() + "Releasing the lock of monitor");
monitor.notifyAll();
monitor.wait();
}
// Thread 3 should print 3
if (atomicInt.get() == 3 && Thread.currentThread().getName().equals("Thread3")) {
// prints 3 and next awakes first thread by setting
// atomic int to 1
atomicInt.set(1);
System.out.println(3);
System.out.println(Thread.currentThread().getName() + "Releasing the lock of monitor");
monitor.notifyAll();
monitor.wait();
}
}
}
} catch (InterruptedException e) {
// catches the interrupted excpeiton
}
}
}

Output :
Thread1Started
Thread2Started
Thread3Started
1
Thread1Releasing the lock of monitor
2
Thread2Releasing the lock of monitor
3
Thread3Releasing the lock of monitor
1
Thread1Releasing the lock of monitor
2
Thread2Releasing the lock of monitor
3
Thread3Releasing the lock of monitor
1
Thread1Releasing the lock of monitor
2
Thread2Releasing the lock of monitor
3
Thread3Releasing the lock of monitor

最新更新