多线程学习笔记(一)

继承Thread类来封装要同步内容

class TestThread extends Thread{ 

void run(){ 处理内容。。。 }

}

// 实现Runnable来实现并封装要同步内容

class TestRunnable implements Runnable{

 public void run(){ 处理内容。。。 } 

}

public class StartRunnable{

 public static void main(String[] args){

  new Thread(new TestRunnable()).start(); 

}

}

//取得当前线程,并判断当前线程是否被中断的。

if(Thread.currentThread().isInterrupted()){ 处理内容。。。}

 //中断线程new TestThread().iterrupt();

如果一个线程被阻塞了,它就无法检查中断状态了。这就是产生IterruptedException异常的地方。当在一个被阻塞的线程上调用interrupt方法时,阻塞调用(例如Sleep或者wait)就会被 InterruptedException异常所终止。中断线程不一定要终止线程,不同的线程对中断有不同的处理方法。

interrupted()方法和isInterrupted()的比较:

interrupted()方法:测试当前线程是否已经中断。线程的中断状态 由该方法清除。换句话说,如果连续两次调用该方法,则第二次调用将返回 false。

isInterrupted()方法:测试线程是否已经中断。线程的中断状态 不受该方法的影响。

 1.3 线程状态

New:新生

Runnable:可运行

Blocked:被阻塞

Dead:死亡

1.3.1 新生状态         

 new Thread();

1.3.2 可运行线程          new Thread().start();    

      这个状态线程不一定时在执行的,也可以处于不执行状态,因为这是有操作系统来安排这个运行时间。记住,这个使Runnable,而不是Running!!!         

 抢占式调度:系统给每个可运行的线程一个时间片来处理任务。当这个时间片用完时,操作系统剥夺该线程对资源的占用,使其他线程有机会运行。现代操作系统都使用这个调度机制。

1.3.3 被阻塞线程         

当发生一下任何一种情况时,线程就进入被阻塞状态:         

1)调用 Sleep方法         

2)线程调用一个在i/o上被阻塞的操作,即这个i/o操作结束之前不会返回到它的调用着         

 3)线程试图获得锁,而这个锁被其他线程占有         

当一个线程被阻塞时候,另一个线程就可以被调度运行了。当一个被阻塞线程重新被激活时,调度起检查它的优先级有没有比当前正在执行的线程优先级高不高,假如高,它就将抢占当前线程的资源,并开始运行。          

通过一下方式线程可以从被阻塞状态回到可运行状态。        

1)Sleep的毫秒数已过时        

2)线程正在等待的i/o操作已经完成时        

3)线程正在等待另一个现成所持有的锁,且另一个线程已经释放该锁        

4)线程正在等待某个出发条件,且另一个线程发出了信号表明条件已经发生了变化。被超时时候也 包括       

5)线程已被挂起,且有人调用它的resume方法。但这个已经被弃用  

1.3.4 死线程      导致死线程的原因如下:     

1)run方法正常退出     

 2)因为一个未捕获的异常中止了run方法而使线程死亡      

isAalive方法:     

测试线程是否处于活动状态(要么是可运行的,要么是被阻塞的)。如果线程已经启动且尚未终止,则为活动状态。     

join(long millis)方法:     

等待该线程终止的时间最长为 millis 毫秒。超时为 0 意味着要一直等下去。

1.4 线程优先级    

线程级别:    

Thread.MIN_PRIORITY : 1    

Thread.MAX_PRIORITY : 10    

Thread.NORM_PRIORITY :5         

public final void setPriority(int newPriority)方法:    

 更改线程的优先级。     

public final int getPriority()方法:   

返回线程的优先级。       

public static void yield()方法:  

暂停当前正在执行的线程对象,并执行其他线程。

1.4.2 守护线程(后台线程)       

public final void setDaemon(boolean on)方法:       

setDeamon(true);设置为守护线程

1.4.3 线程组         

ThreadGroup g = new ThreadGroup(groupName);//groupName是唯一的。         

 Thread t = new Thread(g , threadName);          

public int activeCount()方法:         

返回此线程组中活动线程的估计数。                   

public final void interrupt()方法:        

中断此线程组中的所有线程。        

new Thread().getThreadGroup()方法:        

返回该线程所属的线程组。 如果该线程已经终止(停止运行),该方法则返回 null。

1.5  同步 

1.5.3 锁对象     

jdk5.0引进的ReentrantLock类      

 public void lock()方法:     

获取锁。     

public void unlock()方法:     

试图释放此锁。1.5.4  条件对象     

Condition c = new ReentrantLock().newCondition();     

c.await();/

/造成当前线程在接到信号或被中断之前一直处于等待状态。      

c.signalAll();

//唤醒所有等待线程。       

当一个线程调用了await时,它无法自己解除阻塞状态。它把自己的命运交给了其他线程。如果没有任何其他的线程来接触等待线程的阻塞状态,它就永远也不会运行了,这会导致死锁。    那么应该什么时候调用signalAall呢?例如,当一个账户余额发生变化时,等待线程应该有机会去检查余额。这样使正在因为余额不足而被阻塞的线程去尝试一下条件满不满足。    signalAll的调用不会立即激活等待线程。它只是解除等待线程的阻塞状态,这样这些线程就可以在当前线程退出同步方法后,通过竞争获得对对象的访问。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章