我对JAVA中一个多线程程序的思考

3 篇文章 0 订阅

我之前看到书上一个JAVA多线程的例子,我想学过OS的人看见多线程程序后都会有一些冲动,我也是,二话没说就把代码输到Eclipse中看了一下结果,发现和自己想的一样,结果也很漂亮,然后我就写了一篇日志,下面的源代码不是我写的是书上看到的:

import java.awt.BorderLayout;

import javax.swing.JFrame;

import javax.swing.JProgressBar;

 

public class JoinTest extends JFrame

{

         private Thread threadA;

         private Thread threadB;

         final JProgressBar progressBar1 = new JProgressBar();

         final JProgressBar progressBar2 = new JProgressBar();

         int count = 0;

         public static void main(String[] args)

         {

                   init(new JoinTest(), 200, 200);

         }

        

         public JoinTest()

         {

                   super();

                   getContentPane().add(progressBar1, BorderLayout.NORTH);

                   getContentPane().add(progressBar2, BorderLayout.SOUTH);

                   progressBar1.setStringPainted(true);

                   progressBar2.setStringPainted(true);

                  

                   threadA = new Thread(new Runnable(){

                            int count = 0;

                            public void run(){

                                     while (true){

                                               progressBar1.setValue(++count);

                                               try

                                               {

                                                        threadA.sleep(100);

                                                        threadB.join();

                                               }

                                               catch(Exception e)

                                               {

                                                        e.printStackTrace();

                                               }

                                     }

                            }

                   });

                   threadA.start();

                   threadB = new Thread(new Runnable(){

                            int count = 0;

                            public void run(){

                                     while (true)

                                     {

                                               progressBar2.setValue(++count);

                                               try

                                               {

                                                        threadB.sleep(100);

                                               }

                                               catch(Exception e)

                                               {

                                                        e.printStackTrace();

                                               }

                                               if(count == 100)

                                                        break;

                                     }

                            }

                   });

                   threadB.start();

         }

        

         public static void init(JFrame frame, int width, int height)

         {

                   frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

                   frame.setSize(width, height);

                   frame.setVisible(true);

         }

}

源代码的解释我就不在详细写了,就在前面的日志中,上面的程序是用join来实现的,我们知道join()方法是使当前运行线程暂停,直到调用join的线程运行完毕,当前线程才开始执行,这样我们程序跑起来后结果是:下面的进度条先增长,当下面的进度条增长满后,上面的进度条才开始增长。

前几天看见一位好友在网上发的一篇《求助高手》的日志,我不是高手,不过我还是看了一下他的源代码,返现那个源代码很像我的那段,不知道是不是他看完我的日志后自己改写的。那个好友写的代码如下:

import java.awt.*;

import javax.swing.JFrame;

import javax.swing.JProgressBar;

 

public class JoinTestT extends JFrame

{

         private  int i ;

         private Thread threadA;

         private Thread threadB;

         final JProgressBar progressBar1 = new JProgressBar();

         final JProgressBar progressBar2 = new JProgressBar();

         int count = 0;

         public static void main(String[] args)

         {

                   init(new JoinTestT(), 200, 200);

         }

 

         public JoinTestT()

         {

                   super();

                   getContentPane().add(progressBar1, BorderLayout.NORTH);

                   getContentPane().add(progressBar2, BorderLayout.SOUTH);

                   progressBar1.setStringPainted(true);

                   progressBar2.setStringPainted(true);

 

                   threadA = new Thread(new Runnable(){

                            int count = 0;

                            public void run(){

                                     while (true){

                                               synchronized(this){

                                                        progressBar1.setValue(++count);

                                                        try

                                                        {

                                                                 threadA.sleep(100);

                                                                 while(i != 1){

                                                                          this.wait();

                                                                 }

                                                        }

                                                        catch(Exception e)

                                                        {

                                                                 e.printStackTrace();

                                                        }

                                               }

                                     }

                            }

                   });

                   threadA.start();

                   threadB = new Thread(new Runnable(){

                            int count = 0;

                            public void run(){

                                     while (true)

                                     {

                                               synchronized(this){

                                                        progressBar2.setValue(++count);

                                                        try

                                                        {

                                                                 threadB.sleep(100);

                                                        }

                                                        catch(Exception e)

                                                        {

                                                                 e.printStackTrace();

                                                        }

                                                        if(count == 100){

                                                                 i = 1;

                                                                 this.notify();

                                                                 break;

                                                        }

                                         }

                                     }

 

                            }

                   });

                   threadB.start();

         }

 

         public static void init(JFrame frame, int width, int height)

         {

                   frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

                   frame.setSize(width, height);

                   frame.setVisible(true);

         }

}

       这个程序表面上看上去什么问题也没有,不过程序跑起来后和我们预期的结果一样,思想很简单,先让一个线程跑起来,当该线程的时间片结束后,另外一个线程再开始跑,但是该线程要跑起来需要一个条件要满足,这个条件当前不满足,线程死循环判断,当时间片结束后,第二线程又开始了,这样直到第二个线程结束后,把相应的条件设置好后第一个线程才可以跑,这是我们预期的结果,但是程序跑起来后先是下面的进度条在跑,等下面一个进度条跑满后,上面的进度条卡死不动了,这就就是这个程序的问题。我当时看了很长时间,也没有看出来,我目前只是理论上的推测,但是JAVA的多线程程序我是几乎没有自己动手写过,所以当时看了很长时间也没有找到解决方法,今天中午和一位工程师交流一下,他提出了一种解决方法,我先说一下上面程序错误的原因:原因很简单,线程A中的this对象和线程B中的this对象不是同一个对象,那么线程在一个对象上睡觉,我们在另外一个对象去叫醒在前面那个对象睡觉的线程是不可行的。我当初也以为这里的this对象是同一对象,其实都是内部类对象,他们不是指向同一个对象而是指向各自内部类对象,这里有内部类,这个很重要。下面就是一位工程师给出的解决方案,很漂亮:

import java.awt.*;

import javax.swing.JFrame;

import javax.swing.JProgressBar;

 

public class JoinTestT extends JFrame

{

         private  int i ;

         private Thread threadA;

         private Thread threadB;

         final JProgressBar progressBar1 = new JProgressBar();

         final JProgressBar progressBar2 = new JProgressBar();

         int count = 0;

         public static void main(String[] args)

         {

                   init(new JoinTestT(), 200, 200);

         }

 

         public JoinTestT()

         {

                   super();

                   getContentPane().add(progressBar1, BorderLayout.NORTH);

                   getContentPane().add(progressBar2, BorderLayout.SOUTH);

                   progressBar1.setStringPainted(true);

                   progressBar2.setStringPainted(true);

 

                   threadA = new Thread(new Runnable(){

                            int count = 0;

                            public void run(){

                                     while (true){

                                               synchronized(JoinTestT.this){

                                                        progressBar1.setValue(++count);

                                                        try

                                                        {

                                                                 threadA.sleep(100);

                                                                 while(i != 1){

                                                                           JoinTestT.this.wait();

                                                                 }

                                                        }

                                                        catch(Exception e)

                                                        {

                                                                 e.printStackTrace();

                                                        }

                                               }

                                     }

                            }

                   });

                   threadA.start();

                   threadB = new Thread(new Runnable(){

                            int count = 0;

                            public void run(){

                                     while (true)

                                     {

                                               synchronized(JoinTestT.this){

                                                        progressBar2.setValue(++count);

                                                        try

                                                        {

                                                                 threadB.sleep(100);

                                                        }

                                                        catch(Exception e)

                                                        {

                                                                 e.printStackTrace();

                                                        }

                                                        if(count == 100){

                                                                 i = 1;

                                                                 JoinTestT.this.notify();

                                                                 break;

                                                        }

                                         }

                                     }

 

                            }

                   });

                   threadB.start();

         }

 

         public static void init(JFrame frame, int width, int height)

         {

                   frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

                   frame.setSize(width, height);

                   frame.setVisible(true);

         }

}

       这时候程序跑起来的结果和之前的那段程序跑起来的结果完全一样。我当时看见这位好友写的代码后感触很多,对于程序这东西,我们不能一味的敲别人的代码,那样我们就是充其量是一个高级打字工。别人的程序是要看,但是我相信很多人在看别人的程序的时候会有很多想法,这时候just make it,这句话很重要,我们的想法或许是错的,但是我们会学到很多东西。我也是JAVA的学习者,爱好者,以我目前的实力根本不可能驾驭博大精深的JAVA,所以我还需要跟多的努力,虽然基础好,但是要想学好JAVA也不见的很容易,我也非常感谢这位好友的写的这段代码,使得我学到了一些自己不会的东西,希望你能更上一层楼,期待以后更多的交流。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值