多线程的学习笔记

来源:互联网 发布:沙皇 知乎 编辑:程序博客网 时间:2024/05/01 08:59

           对于单cpu电脑,它会时分复用的执行系统中的多个进程,而每个进程中也会有多个线程。

 

练习1:程序在没有采取多线程技术时,默认单线程执行

 

练习2:程序添加多线程技术以后,类ThreadDemo继承多线程类Thread,实现其run方法。

class ThreadDemol

{

       public static void main(String [] args)

       {

              new ThreadDemo().start();//run();

              while(true)

              {

                            System.out.println("main()"+Thread.currentThread().getName());

              }

       }

}

class ThreadDemo extends Thread

{

       public void run()

       {

              while(true)

              {

                            System.out.println("run()"+Thread.currentThread().getName());

              }

       }

}

 

练习3:后台线程与联合线程

1)  只要还有一个前台线程运行,进程就不会结束。

2)  加入后台线程,进程会很快结束

3)  Thread tt=new ThreadDemo();

              tt.setDaemon(true);

              tt.start();

4)  join()进行线程联合

Thread tt=new ThreadDemo();

              tt.start();

              int index=0;

              while(true)

              {

                            if(index++==100)

                                   try{tt.join();}catch(Exception e){}

                            System.out.println("main()"+Thread.currentThread().getName());

              }

总结:刚开始两个线程交替执行,在主线程执行100次之后,调用tt线程的join方法,只执行tt线程

try{tt.join(5000);}catch(Exception e){}

总结:在join中添加时间,在tt线程执行5秒之后,又开始两个线程交替运行。

 

练习4Thread类的构造方法,用Runnable接口实现多线程

1)  通过继承的方法实现多线程卖票

new ThreadDemo().start();

            new ThreadDemo().start();

            new ThreadDemo().start();

            new ThreadDemo().start();

总结:构建了4个卖票的对象线程,分别卖100张票

2)  通过接口的方法实现多线程卖票

     ThreadDemo tt=new ThreadDemo();

              new Thread(tt).start();

               new Thread(tt).start();

                new Thread(tt).start();

                    new Thread(tt).start();

 

总结:一般多线程都有接口实现,用起来较灵活,一个类可以有多个接口。

 

练习5:多线程的应用

1)  聊天时可以同时执行收发数据的程序

2)  一个循环执行的程序,可以用多线程控制

 

练习6:多线程的同步多线程的控制

1)  synchronized(str)监视器

在需要线程保护的代码块加入synchronized,将str设置为全局变量,当某一线程开始执行时,str的标志位从1变为0,执行结束时str’标志从0变为1当其他的线程想加入时会判断str的状态,如果str0则不能加入,这达到了对某个程序块完整执行的保护。

2)  代码块和函数同步

在代码块上加入this对象,使代码块和函数公用一个对象进行监视。

3)  死锁

当两个呈现原子性的代码块并行运行时,一个代码块在运行时调用另外一个代码块的锁的状态,该代码块将被锁住

1.34分)

练习7:使用多线程进行通信

原始代码:

  class Producer implements Runnable

{

       Q q;

       public Producer(Q q)

       {

              this.q=q;

       }

       public void run()

       {

              int i=0;

              while(true)

              {

                     synchronized(q)

                     {

                            if(q.bFull)

                                   try{q.wait();}catch(Exception e){};

                            if(i==0)

                            {

                                   q.name="zhangsan";

                                   try{Thread.sleep(1);}catch(Exception e){}

                                   q.sex="male";

                            }else

                            {

                                   q.name="lisi";

                                   q.sex="female";

                            }

                            q.bFull=true;

                            q.notify();

                     }

                     i=(i+1)%2;

                    

              }

 

       }

}

class Consumer implements Runnable

{

       Q q;

       public Consumer(Q q)

       {

              this.q=q;

       }

       public void run()

       {

              while(true)

              {

                     synchronized(q)

                     {

                            if(!q.bFull)

                                   try{q.wait();}catch(Exception e){};

                     System.out.print(q.name);

                     System.out.println(":"+q.sex);

                     q.bFull=false;

                     q.notify();

                     }

              }

       }

 

             

}

class Q

{

       String name="unknow";

       String sex="unknow";

       boolean bFull=false;

      

}

class ThreadCommunation

{

       public static void main(String args[])

       {

              Q q=new Q();

              new Thread(new Producer(q)).start();

              new Thread(new Consumer(q)).start();

 

       }

}

代码精简后:

class Producer implements Runnable

{

       Q q;

       public Producer(Q q)

       {

              this.q=q;

       }

       public void run()

       {

              int i=0;

              while(true)

              {

                            if(i==0)

                            {

                                   q.set("zhangsan","male");

                            }else

                            {

                                   q.set("lisi","female");

                            }

                            i=(i+1)%2;

              }

 

       }

}

class Consumer implements Runnable

{

       Q q;

       public Consumer(Q q)

       {

              this.q=q;

       }

       public void run()

       {

              while(true)

              {

                     q.get();

              }

       }

}

class Q

{

       String name="unknow";

       String sex="unknow";

       boolean bFull=false;

       public synchronized void set(String name,String sex)

       {

              if(bFull)

                     try{wait();}catch(Exception e){};

              this.name=name;

              try{Thread.sleep(1);}catch(Exception e){}

              this.sex=sex;

              bFull=true;

              notify();

       }

       public synchronized void get()

       {

              if(!bFull)

                     try{wait();}catch(Exception e){};

              System.out.print(name);

              System.out.println(":"+sex);

              bFull=false;

              notify();

       }

}

class ThreadCommunation

{

       public static void main(String args[])

       {

              Q q=new Q();

              new Thread(new Producer(q)).start();

              new Thread(new Consumer(q)).start();

 

       }

}

 

总结:使在缓存中填入数据和在缓存中读取数据具有原子性,这样就不会在读取姓名zhangsan时,又被中断而读取性别是female,而实现同步。使用waitnotify进行流程控制,使数据放入之后再取,数据取出时再放,使通信更加有效。

练习8:线程控制

源代码:

class ThreadCommunation

{

       public static void main(String args[])

       {

              ThreadTest t=new ThreadTest();

              Thread tt=new Thread(t);

              tt.start();

              for(int i=0;i<100;i++)

              {

                     if(i==50)

                            t.stopMe();

                     System.out.println("main() is running");

              }

 

       }

}

 

class ThreadTest implements Runnable

{

       private boolean bStop=false;

              public void stopMe()

              {

                     bStop=true;

              }

        public void run()

       {

               while(!bStop)

              {

                     System.out.println(Thread.currentThread().getName()+"is runnting");

               }

        }

}

总结:在某个线程上的程序运行结束时,线程自动释放,通过编写代码可以控制线程的生命周期。

 

问题1:既然是后台线程,为什么能看到开始的执行?而不是一开始就什么都看不到

问题2:在通信时用synchrorized和用waitnotify进行控制,是不是会浪费很多资源

 

 

原创粉丝点击