【问题标题】:Print numbers 1-20 with two threads in Java在 Java 中用两个线程打印数字 1-20
【发布时间】:2014-07-13 08:29:22
【问题描述】:

我正在尝试用两个线程打印数字 1-20:

  • 偶数线程 - 仅打印偶数。
  • 奇数线程 - 仅打印奇数。

我还有一个用于同步的锁对象。

我的应用程序卡住了。你能告诉我是什么问题吗?

我的代码:

public class runIt
{

    public static void main(String[] args)
    {
        Odd odd = new Odd("odd thread");
        Even even = new Even("even thread");

        odd._t.start();
        even._t.start();

        try{
            odd._t.join();
            even._t.join();
        }
        catch (InterruptedException e){
            System.out.println(e.getMessage());
        }   
    }
}

public class Constants{
    static Object lock = new Object();
}

public class Even implements Runnable{
    Thread  _t;
    String  _threadName;

    public Even(String threadName){
        _threadName = threadName;
        _t = new Thread(this);
    }

    @Override
    public void run(){
        for (int i = 0; i < 20; i++){
            if (i % 2 == 0){
                synchronized (Constants.lock){                  
                    try{
                        Constants.lock.wait();
                        Constants.lock.notifyAll();
                    }
                    catch (InterruptedException e){
                        e.printStackTrace();
                    }
                    System.out.println(_threadName + " " + i + " ");
                }
            }
        }
    }
}

public class Odd implements Runnable{
    Thread  _t;
    String  _threadName;

    public Odd(String threadName){
        _threadName = threadName;
        _t = new Thread(this);

    }

    @Override
    public void run(){
        for (int i = 0; i < 20; i++){
            if (i % 2 == 1){
                synchronized (Constants.lock){                  
                    try{
                        Constants.lock.wait();
                        Constants.lock.notifyAll();
                    }
                    catch (InterruptedException e1){
                        e1.printStackTrace();
                    }
                    System.out.println(_threadName + " " + i + " ");
                }
            }
        }
    }
}

我的输出应该是:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20

感谢您的帮助, 谭。

【问题讨论】:

  • 看看这里:stackoverflow.com/questions/6017281/… 这似乎正是你所需要的。
  • 所以我想这意味着新学期刚刚开始? 叹息
  • 您的直接问题是两个线程都进入了锁等待状态,然后它们永远不会收到通知。不过,此代码还存在一些其他问题。
  • @WarrenDew 说,“还有一些其他问题......”这是一个:你在构造函数中写了new Thread(this)。在这段代码中,这可能不会对您造成任何问题,但是如果您想知道为什么它通常是一个坏主意,请使用谷歌“在构造函数中泄漏它”。

标签: java multithreading thread-safety deadlock thread-synchronization


【解决方案1】:

您可以在 package declaraion 中提到的站点中找到解释: 这是工作代码:

public class MultipleThreading {
    int count = 1;
    int MAX = 20;

    public void printOdd() {
    synchronized (this) {
        while (count < MAX) {
        while (count % 2 == 0) {
            try {
            wait();
            } catch (InterruptedException e) {
            e.printStackTrace();
            }
        }
        System.out.print(count + " ");
        count++;
        notify();
        }
    }
    }

    public void printEven() {
    synchronized (this) {
        while (count < MAX) {
        while (count % 2 == 1) {
            try {
            wait();
            } catch (InterruptedException e) {
            e.printStackTrace();
            }
        }
        System.out.print(count + " ");
        count++;
        notify();
        }
    }
    }

    public static void main(String[] args) {
    MultipleThreading mt = new MultipleThreading();
    Thread t1 = new Thread(new Runnable() {
        @Override
        public void run() {
        mt.printEven();
        }
    });
    Thread t2 = new Thread(new Runnable() {
        @Override
        public void run() {
        mt.printOdd();
        }
    });
    t1.start();
    t2.start();
    }
}

【讨论】:

    【解决方案2】:

    您正在滥用synchronizedwait,立即对您在synchronized 中使用的对象调用wait,而没有检查循环中的同步块内部再也不要这样做了

    实际上是这样的:

    • synchronized 行,您可以锁定Constants.lock
    • wait 行,您释放Constants.lock 上的锁定并等待来自另一个线程的通知。

    那么你的 prog 中发生了什么:

    • 第一个线程(不管它是什么)到达synchronized 并继续阻塞第二个线程
    • 第一个线程释放同步锁并将自己置于等待通知状态
    • 第二个线程通过synchronized,因为第一个已经释放了锁
    • 两个线程现在都在等待一个永远不会发生的通知

    【讨论】:

    • 这是一个相当古老的问题,但我记得它是关于什么的。我说过永远不要再这样做了,因为这是制造僵局的秘诀……
    【解决方案3】:

    以下代码将对某人有所帮助,

    public class MyClass {
    
    private static Object lock = new Object();
    
    public static void main(String args[]){
    
        Runnable runnable1 = new Runnable() {
            @Override
            public void run() {
                for(int i=1; i<20; i=i+2){
                    synchronized (lock) {
                        System.out.println("Thread 1: "+i);
                        try {
                            lock.notifyAll();
                            lock.wait();
                        } catch (InterruptedException e) {
                            System.out.println("Error in Thread 1: "+e.getMessage());
                        }
                    }
                }
            }
        };
    
    
        Runnable runnable2 = new Runnable() {
            @Override
            public void run() {
                for(int i=2; i<=20; i=i+2){
                    synchronized (lock) {
                        System.out.println("Thread 2: "+i);
                        try {
                            lock.notifyAll();
                            lock.wait();
                        } catch (InterruptedException e) {
                            System.out.println("Error in Thread 2: "+e.getMessage());
                        }
                    }
                }
            }
        };
    
        Thread thread1 = new Thread(runnable1);
        Thread thread2 = new Thread(runnable2);
    
        System.out.println("Thread Start: ");
        thread1.start();
        thread2.start();               
    }
    
    }
    

    【讨论】:

      【解决方案4】:

      Stack Overflow 上的每个人都尝试了相同的解决方案。检查相同的不同实现。

      public class PrintSequenceUsingTwo {
      
          public static void main(String[] args) {
              ThreadSequence sequence = new ThreadSequence();
              Thread t1 = new Thread(()-> {try {
                  sequence.print();
              } catch (InterruptedException e) {
                  e.printStackTrace();
              }},"t1");
              Thread t2 = new Thread(()-> {try {
                  sequence.print();
              } catch (InterruptedException e) {
                  e.printStackTrace();
              }},"t2");
      
              t1.start();
              t2.start();
              try {
                  t1.join();
                  t2.join();
              } catch (Exception e) {
                  e.printStackTrace();
              }
          }
      }
      

      class ThreadSequence {
      
          private static int var = 0; 
          private int limit = 10;     //set the variable value upto which you want to print
      
          public synchronized void print() throws InterruptedException {
              while (var<limit) {
                  notify();
                  System.out.println("Current Thread "+Thread.currentThread().getName()+" Value : "+(++var));
                  wait();
              }
              notify();
          }
      }
      

      【讨论】:

        【解决方案5】:
        public class Print1To20 {
        
            int couter=0;
            static int N;
        
            public void preven(){
                synchronized (this) {
                    while(couter<N) {
                        while(couter%2==0) {
                            try {
                                wait();
                            } catch(Exception e) {
                            }
                            System.out.println(Thread.currentThread().getName()+":"+couter);
                        }
                        couter++;
                        notify();
                    }
                }
            }
            public void prodd(){
                synchronized (this) {
                    while(couter<N) {
                        while(couter%2==1) {
                            try {
                                wait();
                            } catch(Exception e) {
                            }
                            System.out.println(Thread.currentThread().getName()+":"+couter);
                        }
                        couter++;
                        notify();
                    }
                }
            }
            
            public static void main(String[] args) {
                // TODO Auto-generated method stub
        
                //  Thread t1= new Th;
        
                //Thread t2= new Thread(new PrintOdd());
        
                N=20;
                Print1To20 pt= new Print1To20();
                Thread t1= new Thread(new Runnable() {
                    @Override
                    public void run() {
                        // TODO Auto-generated method stub
                        pt.preven();
                    }
                });
        
                Thread t2= new Thread(new Runnable() {
                    @Override
                    public void run() {
                        // TODO Auto-generated method stub
                        pt.prodd();
                    }
                });
                t1.start();
                t2.start();
            }
        }
        

        参考:参考来自 GeekforGeeks

        【讨论】:

        • 如果可能的话,也附上 geeksforgeeks 链接。
        【解决方案6】:
        Try this solution.....
        
        public class Print1To20Using2Thread {
            public static void main(String[] args) {
                PrintNumber pn = new PrintNumber(new Object());
                Thread t1 = new Thread(pn, "First");
                Thread t2 = new Thread(pn, "Second");
        
                t1.start();
                t2.start();
            }
        }
        
        class PrintNumber implements Runnable {
        
            Object lock;
            int i = 0;
            public PrintNumber(Object lock) {
                this.lock = lock;
            }
        
            @Override
            public void run() {
                synchronized (lock) {
                    for (; i <= 20; i++) {
                        if (i == 11) {
                            try {
                                lock.wait(1000);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                        System.out.print(" "+Thread.currentThread().getName() + " " + i);
                        lock.notifyAll();
                    }
                    System.out.println();
                }
            }
        }
        

        【讨论】:

        • 为你的答案添加一些解释
        猜你喜欢
        • 2018-01-25
        • 1970-01-01
        • 2013-05-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-03-17
        • 1970-01-01
        相关资源
        最近更新 更多