继承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的调用不会立即激活等待线程。它只是解除等待线程的阻塞状态,这样这些线程就可以在当前线程退出同步方法后,通过竞争获得对对象的访问。