关于线程知识的总结

一、调用多线程

如何在自己定义的方法中定义一个线程呢?
创建线程的一种方式:继承Thread类。
步骤:
1,定义类继承Thread;
2,复写Thread类中的run方法。
目的:将自定义的代码存储在run方法中,让线程运行。
3,调用线程的start方法,该方法的两个作用:启动线程,调用run方法。
4,发现运行结果每一次都不同
5,因为多个线程都获取CPU的执行权,CPU执行到谁谁就运行,多核除外。
CPU做着快速的切换,已达到看上去同时执行的效果。我们可以形象的把多线程的运行行为在抢夺CPU的资源,这就是多相程的一个特性。
这就是:随机性。至于执行多长时间由CPU决定。
6,线程都有自己的默认名称getName();



为什么要覆盖RUN方法?

Thread类用于描述线程。
该类就定义了一个功能,用于存储要运行的代码。该存储功能就是run方法。也就是说Thread类中的run方法用于存储要运行的代码。
因为Thread类中的run方法是空的方法,所以要继承thread类重写run方法。

class Demo extends Thread
{
     public void run()
     {
          for (int x=0;x<60 ;x++ )
          {
               System.out.println("demo run--------"+x);
          }
         
     }
}

class  ThreadDemo
{
     public static void main(String[] args)
     {
          //System.out.println("Hello World!");

          Demo d = new Demo(); 
          d.start();//开启线程并执行该线程的run方法。

          //d.run();//仅仅是对象调用方法。而线程创建了,并没有运行。
          fo
r (int i=0;i<60 ;i++ )
          {
               System.out.println("HelloWord");
          }

     }
}


 二、java中继承Thread类与实现Runnable接口的区别

1.  通过继承Thread类,重写Thread的run()方法,将线程运行的逻辑放在其中

2.  通过实现Runnable接口,实例化Thread类

 

    在实际应用中,我们经常用到多线程,如车站的售票系统,车站的各个售票口相当于各个线程。当我们做这个系统的时候可能会想到两种方式来实现,继承Thread类或实现Runnable接口,现在看一下这两种方式实现的两种结果。


Java代码  收藏代码
  1. package com.threadtest;  
  2. class MyThread extends Thread{  
  3.       
  4.     private int ticket = 10;  
  5.     private String name;  
  6.     public MyThread(String name){  
  7.         this.name =name;  
  8.     }  
  9.       
  10.     public void run(){  
  11.         for(int i =0;i<500;i++){  
  12.             if(this.ticket>0){  
  13.                 System.out.println(this.name+"卖票---->"+(this.ticket--));  
  14.             }  
  15.         }  
  16.     }  
  17. }  
  18. public class ThreadDemo {  
  19.   
  20.       
  21.     public static void main(String[] args) {  
  22.         MyThread mt1= new MyThread("一号窗口");  
  23.         MyThread mt2= new MyThread("二号窗口");  
  24.         MyThread mt3= new MyThread("三号窗口");  
  25.         mt1.start();  
  26.         mt2.start();  
  27.         mt3.start();  
  28.     }  
  29.   
  30. }  

 

运行结果如下:

Java代码  
  1. 一号窗口卖票---->10  
  2. 一号窗口卖票---->9  
  3. 二号窗口卖票---->10  
  4. 一号窗口卖票---->8  
  5. 一号窗口卖票---->7  
  6. 一号窗口卖票---->6  
  7. 三号窗口卖票---->10  
  8. 一号窗口卖票---->5  
  9. 一号窗口卖票---->4  
  10. 一号窗口卖票---->3  
  11. 一号窗口卖票---->2  
  12. 一号窗口卖票---->1  
  13. 二号窗口卖票---->9  
  14. 二号窗口卖票---->8  
  15. 三号窗口卖票---->9  
  16. 三号窗口卖票---->8  
  17. 三号窗口卖票---->7  
  18. 三号窗口卖票---->6  
  19. 三号窗口卖票---->5  
  20. 三号窗口卖票---->4  
  21. 三号窗口卖票---->3  
  22. 三号窗口卖票---->2  
  23. 三号窗口卖票---->1  
  24. 二号窗口卖票---->7  
  25. 二号窗口卖票---->6  
  26. 二号窗口卖票---->5  
  27. 二号窗口卖票---->4  
  28. 二号窗口卖票---->3  
  29. 二号窗口卖票---->2  
  30. 二号窗口卖票---->1  

 

通过实现Runnable接口的代码如下:
 

  1. package com.threadtest;  
  2. class MyThread1 implements Runnable{  
  3.     private int ticket =10;  
  4.     private String name;  
  5.     public void run(){  
  6.         for(int i =0;i<500;i++){  
  7.             if(this.ticket>0){  
  8.                 System.out.println(Thread.currentThread().getName()+"卖票---->"+(this.ticket--));  
  9.             }  
  10.         }  
  11.     }  
  12. }  
  13. public class RunnableDemo {  
  14.   
  15.       
  16.     public static void main(String[] args) {  
  17.         // TODO Auto-generated method stub  
  18.         //设计三个线程  
  19.          MyThread1 mt = new MyThread1();  
  20.          Thread t1 = new Thread(mt,"一号窗口");  
  21.          Thread t2 = new Thread(mt,"二号窗口");  
  22.          Thread t3 = new Thread(mt,"三号窗口");  
  23. //         MyThread1 mt2 = new MyThread1();  
  24. //         MyThread1 mt3 = new MyThread1();  
  25.          t1.start();  
  26.          t2.start();  
  27.          t3.start();  
  28.     }  
  29.   
  30. }  

 

运行结果如下:

 

 

    为什么会出现这种结果呐。我们不妨做个比喻,其实刚的程序,

继承Thread类的,我们相当于拿出三件事即三个卖票10张的任务分别分给三个窗口,他们各做各的事各卖各的票各完成各的任务,因为MyThread继承Thread类,所以在new MyThread的时候在创建三个对象的同时创建了三个线程;

实现Runnable的, 相当于是拿出一个卖票10张得任务给三个人去共同完成,new MyThread相当于创建一个任务,然后实例化三个Thread,创建三个线程即安排三个窗口去执行。

     

用图表示如下:


 

   在我们刚接触的时候可能会迷糊继承Thread类和实现Runnable接口实现多线程,其实在接触后我们会发现这完全是两个不同的实现多线程,一个是多个线程分别完成自己的任务,一个是多个线程共同完成一个任务。

    其实在实现一个任务用多个线程来做也可以用继承Thread类来实现只是比较麻烦,一般我们用实现Runnable接口来实现,简洁明了。

 大多数情况下,如果只想重写 run() 方法,而不重写其他 Thread 方法,那么应使用 Runnable 接口。这很重要,因为除非程序员打算修改或增强类的基本行为,否则不应为该类(Thread)创建子类。


        三、线程安全问题


多线程在运行时会出现安全问题
问题的原因是:

当多条语句在操作同一个线程共享数据时,一个线程对多条语句只执行了一部分,而另一个线程又参与了进来执行,
导致共享数据的错误。

解决办法是:
对多条操作共享数据语句的时候,在执行过程中只能让一个线程都执行完,其他线程才能参与执行。
java对于多线程的安全问题提供了专业的解决方法。
就是同步代码块。
synchronized(对象)
{
需要同步的代码块
}
就是锁旗标的标志位的改变(0,1)。
对象如同锁。持有锁的线程可以在同步中执行。
没有持有锁的线程即使获取CPU的执行权,也进不去,应为没有获取锁。

同步的前提Z:
1.两个或两个以上的线程运行时。
2.必须是多个线程同时使用同一个资源。
必须保证线程中只能有一个线程在运行。

好处:解决了多线程的安全问题。
弊端:应为每次要判断锁,所以消耗了资源,效率比较缓慢。



class Ticket implements Runnable
{
     private int tick = 100;
     public void run()
     {
          while (true)
          {
               synchronized
               {
                   if (tick>0)
                   {
                        try(Thread.sleep(10);)catch(Exception e){}
                        System.out.println(Thread.currentThread().getName()+"......name"+tick--);
                   }
               }
          }
     }
}



class Test110
{
     public static void main(String[] args)
     {
          //System.out.println("Hello World!");
          Ticket t=new Ticket();

          Thread t1=new Thread(t);
          Thread t2=new Thread(t);
          Thread t3=new Thread(t);
          Thread t4=new Thread(t);

     }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值