1、线程的使用
1.1 线程的使用有两种方式:继承Thread、继承Runnable
//使用继承Thread方式
class MThread extends Thread {
@Override
public void run() {
System.out.println("==>MThread run");
}
}
class MRun implements Runnable{
private boolean isRun = true;
@Override
public void run() {
while(isRun)
System.out.println("==>MRun");
}
//停止线程的最好方式
public void stop(){
this.isRun = false;
}
}
public class Test {
public static void main(String[] args){
//使用继承Thread方式
new MThread().start();
//使用实现Runnable的方式
new Thread(new MRun()).start();
//多线程共享同一个Runnable
MRun run = new MRun();
new Thread(run).start();
new Thread(run).start();
}
}
2、线程的状态
线程有6种状态
2.1 新建:new Thread()时的状态,此时并未运行run方法中的代码
2.2 可运行:一旦调用了start()方法,线程就处于可运行状态。但是此时线程可能正在运行,也可能没有运行
2.3 被阻塞:当线程试图获取锁,而该锁被其他线程持有,线程进入被阻塞状态。当获取锁时,线程变为非阻塞状态
2.4 等待:当线程等待另一个线程通知调度器一个条件,该线程将进入等待状态。在调用Object.wait、Thread.join时,会出现等待状态。
等待状态与被阻塞状态不同
2.5 超时:有些方法有超时参数,调用他们将使线程进入计数等待状态。这一状态将一直保持到超时或者收到适当的通知。这些方法有Thread.sleep/Lock.tryLock
2.6 被终止
线程终止有两种方式:
run方法执行完
一个未捕获的异常导致run方法意外退出
当线程被阻塞、等待时,另一个线程被调度为可运行状态。当该线程重新被激活进入可运行状态,调度器会检查它是否具有比正在运行线程更高的优先级,如果更高,调度器会暂停一个正在运行的线程,运行此线程。
3、线程属性
3.1 线程的优先级
每个线程都有一个优先级,默认情况下会继承父类的优先级。使用setPriority方法可以设置,范围为1~10
线程的优先级高度依赖系统。sun为linux提供的线程优先级被忽略,即所有的优先级都相同
3.2 守护线程
Thread.setDaemon(true);方法将线程设置为守护线程。
守护线程唯一的作用就是为其他线程提供服务。当只剩下守护线程时,虚拟机会退出
3.3 interrupt
用来设置中断状态,true为中断状态。我们调用sleep、wait等此类可中断(throw InterruptedException)方法时,一旦方法抛出InterruptedException,当前调用该方法的线程的中断状态就会被jvm自动清除了。如果你想保持中断状态,可以再次调用interrupt方法设置中断状态。检测状态可以使用isInterrupted。标记为中断状态不会停止线程,需要用户做具体处理
interrupted返回的是当前线程的中断状态,同时将当前线程状态置位
3.4 未捕获异常处理器
线程的run方法不能抛出任何被检测的异常,不被检测的异常会导致线程终止。出异常的线程不会影响到其他线程,所以其他线程也不能知道一个线程因为异常而终止。
如果需要捕获这个异常,可以实现Thread.UncaughtExceptionHandler接口,或者使用Thread.setDefaultUncaughtExceptionHandler方法。
调用步骤:
如果该线程组有父线程组,则先调用父线程组的uncaughtException方法
如果Thread.getDefaultUncaughtExceptionHandler()返回一个非空处理器,调用之
如果Throwable是ThreadDeath的一个实例,则什么都不做
否则 线程名字及Throwable的栈踪迹被输出到System.err上
http://blog.youkuaiyun.com/u010853261/article/details/61419677
4、Callable和Future
4.1 Runnable封装一个异步执行任务,run方法没有参数、没有返回值
4.2 Callable与Runnable类似,但是有返回值且可以抛异常
public interface Callable<V> {
/**
* Computes a result, or throws an exception if unable to do so.
*
* @return computed result
* @throws Exception if unable to compute a result
*/
V call() throws Exception;
}
4.3 Future 比Callable更强大
public interface Future<V> {
//将会被阻塞,知道有返回值
V get() throws InterruptedException, ExecutionException;
V get(long timeout, TimeUnit unit)
throws InterruptedException,ExecutionException, TimeoutException;
}
4.4 FutureTask
继承Runnable, Future
2、同步基础
2.1 synchronized
synchronized锁有两种用法:
锁方法
锁对象
锁对象时,要保证对象的唯一性。
同步是一种高开销的操作,因此应该尽量减少同步的内容。通常没有必要同步整个方法,使用synchronized代码块同步关键代码即可。
2.2 wait与notify
Object.wait使线程进入等待状态,直到它被其他线程通过notify()或者notifyAll唤醒。该方法只能在同步方法中调用,即Object.wait()和Object.notify()和Object.notifyall()必须写在synchronized方法内部或者synchronized块内部。如果当前线程不是锁的持有者,该方法抛出一个IllegalMonitorStateException异常。
void wait(long millis)超时版本
wait进入等待状态会释放锁,但是sleep不会
notifyAll在wait之前调用,不会影响到wait的线程
2.3 volatile
多线程下,每个线程获得的volatile修饰的变量都是最新值,不提供原子性
2.4 ThreadLocal
每个线程都有私有内存,使用私有内存,各个线程互不影响
2.5 原子变量
2.6 JUC
生产者消费者
class Service{
public int index;
public LinkedList<Integer> list = new LinkedList<Integer>();
public final static int MAX = 100;
public void produce() {
synchronized (list) {
try {
//如果货物已满 则等待消费
while (list.size() >= MAX) {
System.out.println(Thread.currentThread().getName()+"工厂==>仓库有 " + list.size()+" 个商品 已经无法生产");
list.wait();
}
this.list.offer(++this.index);
System.out.println(Thread.currentThread().getName()+"工厂==>仓库有 " + this.list.size()+" 个商品");
Thread.currentThread().sleep(50);
list.notify();
}catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void custom() {
synchronized (list) {
try {
//如果没有物品 需要等待生产
while (this.list.size() <= 0) {
System.out.println(Thread.currentThread().getName()+" 消费==>仓库有 " + this.list.size()+" 个商品 等待工厂生产");
list.wait();
}
this.list.pop();
System.out.println(Thread.currentThread().getName()+"消费==>仓库有 " + this.list.size()+" 个商品");
Thread.currentThread().sleep(80);
list.notify();
}catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Producer extends Thread{
private Service service;
public Producer(Service service) {
this.service = service;
}
@Override
public void run() {
while(true)
this.service.produce();
}
}
class Customer extends Thread{
private Service service;
public Customer(Service service) {
this.service = service;
}
@Override
public void run() {
while(true)
this.service.custom();
}
}
public class Test{
public static void main(String[] args) {
Service service = new Service();
new Producer(service).start();
new Producer(service).start();
new Producer(service).start();
new Customer(service).start();
new Customer(service).start();
}
}