分享

范例解说Java里的线程概念与线程同步技术(二) - JAVA专栏

 汲取者 2010-05-06

本文以通俗易懂的范例入手,由浅入深的全面介绍了Java里的线程概念与线程同步技术。

Page:  <1|2>


线程的创建
创 建新执行线程有两种方法。
方法一种方法是将类声明为 Thread 的子类。该子类应重写 Thread 类的 run 方法。事实上类Thread本身也实现了接口Runnable,所以我们可以同过继承Thread类实现线程体。
参考:SellBookThread.javaCallSellBook.java
另 一种方法是声明实现 Runnable 接口的类。该类然后实现 run 方法。
参考:SellBookRunnable.javaCallSellBook.java



线程的状态
线程有四种状态:创建状态(New),可运行状态(Runnable),阻塞状态(Blocked),死亡状态(Dead)。

创建状态 (New):
当执行完
Thread t1 = new SellBookThread("SaleMan1", bookList);
语句之后,则t1处于创建状态(New)。此时t1并未真正运行。

可运行状态(Runnable):
当Thread t1被创建,并执行完
t1.start();
语句之后,t1就处于可运行状态(Runnable)。此时,系统为线程t1分配其所需的系统资源。并对t1加以调用(或者根据任务调度情况准备调用)。

阻塞状态(Blocked):
由于以下原因:
1) 调用了sleep()方法;
2) 调用了suspend()方法(该方法已不推荐使用);
3) 为等待条件锁,调用wait()方法等;
4) 输入输出,或消息发生阻塞;

使 得线程处于阻塞状态(Blocked)。处于该状态的线程即使处理器空闲,也不会得到执行。

死亡状态(Dead):
死亡状态 (Dead)可以为自然死亡(线程运行完毕),或者调用了stop()方法(该方法已不推荐使用)。


线程的优先级:
可以通过 Thread类的    
void setPriority(int newPriority)
方法为线程设置优先级。但是不能保证高优 先级的线程就会被先运行。

线程组:
可以通过
ThreadGroup group = new ThreadGroup(groupName);
Thread t1 = new Thread(ThreadGroup g, Runnable r1);
Thread t1 = new Thread(ThreadGroup g, Runnable r2);
等 方法把多个线程加到一个线程组里去,这样可以通过ThreadGroup对这些线程进行某些统一操作,
例 如:group.interrupt();中断该组所有线程。


线程unchecked异常处理器:
可以通过:
public void static Thread.setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler)
方 法为所有线程指定一个unchecked异常处理器,该处理器必须实现UncaughtExceptionHandler接口。


线程同步:
线程同步指多个线程 同时访问某资源时,采用一系列的机制以保证同时最多只能一个线程访问该资源。
线程同步是多线程中必须考虑和解决的问题,因为很可能发生多个线程同 时访问(主要是写操作)同一资源,如果不进行线程同步,很可能会引起数据混乱,造成线程死锁等问题。

使用synchronized同步线 程。
在J2SE5.0之前,只能使用synchronized来同步线程。可以使用synchronized来同步代码块或者方法。
同步 代码块例:
synchronized(欲同步的对象obj) {需要同步的代码块}可以同步代码块。

参考:SellBookThread.java
  1.     private void sellBook(Book book) {  
  2.         synchronized (book) {  
  3.             ...  
  4.         }  
  5.     }  

该例synchronized (book) 表示若多个线程同时访问时,只让其中一个线程最先取得book对象,其它线程则阻塞直到代码块执行完毕book对象被释放后,其它线程才能取得该book 对象继续执行。
很多情况下,可以使用synchronized (this){...}来同步代码块。但需要注意的是,使用this作为同步对象的话,如果同一个类中存在多个synchronized (this){...}代码块,其中任何一个synchronized(this)代码块处于被执行状态,则其它线程对其他 synchronized(this)代码块的访问也会受到阻塞。

同步方法例:
  1. synchronized private void sellBook(Book book) {  
  2. ...  
  3. }  

这种方法其实相当于
  1. private void sellBook(Book book) {  
  2.     synchronized(this) {  
  3.         ...  
  4.     }  
  5. }  

由于默认采用this作为同步对象,所以当一个类中有多个synchronized方法时,同样会存在以上问题:即如果 有一个线程访问其中某个synchronized方法时,直到该方法执行完毕,其它线程对其它synchronized方法的访问也将受到阻塞。
有 关synchronized详细说明我们将在其它文章中加以说明。


使用 java.util.concurrent.locks.ReentrantLock和 java.util.concurrent.locks.ReentrantReadWriteLock类同步线程。
J2SE5.0加入了 ReentrantLock和ReentrantReadWriteLock可以对线程进行同步,这里举一个最简单的例子对其加以说明:
  1.  class X {  
  2.    private final ReentrantLock lock = new ReentrantLock();  
  3.    // ...  
  4.   
  5.    public void m() {   
  6.      lock.lock();  // block until condition holds  
  7.      try {  
  8.        // ... method body  
  9.      } finally {  
  10.        lock.unlock()  
  11.      }  
  12.    }  
  13.  }  
  14.    



其它J2SE5.0新导入的有关线程的相关接口/类:
java.util.concurrent.Future
Future 接口可以保持/取得异步执行的结果值

java.util.concurrent.Callable
类似于Runnable接口。 但Runnable不能返回值,也不能抛出checked异常

java.util.concurrent.ExecutorService
该 接口继承了Executor接口。可以通过submit方法把Runnable,Callable对象转换为Future 形式。

java.util.concurrent.FutureTask
该 类实现了Runnable和Future接口。提供异步执行的取消以及异步执行结果的取得等功能。

java.util.concurrent.Executor
执 行指定的Runnable对象

java.util.concurrent.Executors
工具类。提供静态方法可以创建 Executor,ExecutorService,Callable等对象。可以通过newCachedThreadPool()等方法简单创建线程 池。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多