一、先简单粗暴解释一下一些与线程有关的概念
  1.并行与并发
   并行:多个cpu实例或者多台机器同时执行一段处理逻辑,是真正的同时。
   并发:通过cpu调度算法,让用户看上去同时执行,实际上从cpu操作层面不是真正的同时。
  2.资源共享
   多个线程调用资源,是同一个或多个资源。
  3.线程安全
   在并发的情况之下,代码经过多线程使用,线程的调度顺序不影响最后结果,则是线程安全的。
  3.同步
    Java中的同步指的是通过人为的控制和调度,保证共享资源的多线程访问成为线程安全。例如使用@synchronized。

  Java线程具有五中基本状态

  新建状态(New):当线程对象对创建后,即进入了新建状态,如:Thread t = new MyThread();

  就绪状态(Runnable):当调用线程对象的start()方法(t.start();),线程即进入就绪状态。处于就绪状态的线程,只是说明此线程已经做好了准备,随时等待CPU调度执行,并不是说执行了t.start()此线程立即就会执行;

  运行状态(Running):当CPU开始调度处于就绪状态的线程时,此时线程才得以真正执行,即进入到运行状态。注:就绪状态是进入到运行状态的唯一入口,也就是说,线程要想进入运行状态执行,首先必须处于就绪状态中;

  阻塞状态(Blocked):处于运行状态中的线程由于某种原因,暂时放弃对CPU的使用权,停止执行,此时进入阻塞状态,直到其进入到就绪状态,才 有机会再次被CPU调用以进入到运行状态。根据阻塞产生的原因不同,阻塞状态又可以分为三种:

   1.等待阻塞:运行状态中的线程执行wait()方法,使本线程进入到等待阻塞状态;

   2.同步阻塞 -- 线程在获取synchronized同步锁失败(因为锁被其它线程所占用),它会进入同步阻塞状态;

   3.其他阻塞 -- 通过调用线程的sleep()或join()或发出了I/O请求时,线程会进入到阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕    时,线程重新转入就绪状态。

  死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期   
二、实现Runnable接口相比继承Thread类有以下好处:
1.避免单继承的局限,一个类可以实现多个接口
2.适合资源的共享。

通过例子说明资源共享:
  Runnable接口:
  
  测试:
  
  结果:明显Runnable可以实现资源共享
  

Thread父类:

  

  测试:

  

  结果:没有实现资源共享

  

 

总结: 

(资源共享)
  java多线程访问共享资源的方式:
    (1).如果每个线程执行的代码相同,可以使用同一个Runnable对象,这个Runnable对象中有那个共享数据。
    (2).如果每个线程执行的代码不同,这时候需要使用不同的Runnable对象,这种情况有两种方式实现:
    1.将共享资源封装在另一个对象中,然后将这个对象逐一传给各个Runnable对象(在java中,对象(同过new来生成的对象)作为参数传递时,传递的是对    象的地址),每个线程对共享数据的操作方法也分配到那个对象身上去完成,这样容易实现针对该数据进行各个操作的互斥和通信。
    2.将这些Runnable对象作为某一个类中的内部类,共享数据作为这个外部类中的成员变量,每个线程对共享数据的操作也分配给外部类,以便实现对共享    数据进行各个操作的互斥和通信,作为内部类的各个Runnable对象调用外部类的这些方法。
      总之,要同步互斥的几段代码最好放在几个独立的方法中,这些方法再放在一个类中,这样比较容易实现他们之间的互斥和通信。
    (3).简单极端的方式,在任意一个类中定义一个static变量,static变量将被所有线程共享
 
(同步)。同步方法/同步代码块
    注:同步是一种高开销的操作,因此应该尽量减少同步的内容。
       通常没有必要同步整个方法,使用synchronized代码块同步关键代码即可。
 
 

 

  

posted on 2017-08-13 18:34  张超五  阅读(299)  评论(0编辑  收藏  举报