多线程
多个线程并发执行的技术
进程和线程
一句话:进程是操作系统资源分配的基本单位,而线程是任务调度和执行的基本单位,线程是进程的一部分。
java多线程
- 状态
- 关键字
- 使用
线程状态
- 新建状态: 没有调用start()方法之前
- 就绪状态: 调用start()方法之后线程就进入就绪状态,阻塞恢复的时候也会进入就绪状态
- 运行状态: 线程被设置为当前线程,开始执行run()方法
- 阻塞状态: 线程被暂停,比如说调用sleep()方法后线程就进入阻塞状态
- 死亡状态: 线程执行结束
线程关键字
- synchronized
- volatile
- ThreadLocal
- Lock
- ThreadPoolExecutor
关键字解析(纯代码+注释)
- synchronized
反例—不用synchronized带来什么问题
public class A
{
public static int a = 0;
public int add()
{
try
{
//注意 sleep 使线程休眠,不释放锁
Thread.sleep(1000);
} catch (InterruptedException e)
{
}
System.out.println("当前线程是: " + Thread.currentThread().getName() + " before a=" + a + " after a=" + ++a);
return a;
}
public static void main(String[] args)
{
A a = new A();
/**
* t1线程执行5次A add方法
*/
Thread t1 = new Thread(new Runnable()
{
@Override
public void run()
{
a.add();
}
});
/**
* t2线程执行1次A add方法,但是需要干别的是耽误了一些时间,最终得到的结果却不对
*/
Thread t2 = new Thread(new Runnable()
{
@Override
public void run()
{
a.add();
}
});
t2.start();
t1.start();
}
}
执行结果
当前线程是: Thread-0 before a=0 after a=2
当前线程是: Thread-1 before a=0 after a=1
使用synchronized得到想要的
public class A
{
public static int a = 0;
public synchronized int add()
{
try
{
//注意 sleep 使线程休眠,不释放锁
Thread.sleep(1000);
} catch (InterruptedException e)
{
}
System.out.println("当前线程是: " + Thread.currentThread().getName() + " before a=" + a + " after a=" + ++a);
return a;
}
public static void main(String[] args)
{
A a = new A();
/**
* t1线程执行5次A add方法
*/
Thread t1 = new Thread(new Runnable()
{
@Override
public void run()
{
a.add();
}
});
/**
* t2线程执行1次A add方法,但是需要干别的是耽误了一些时间,最终得到的结果却不对
*/
Thread t2 = new Thread(new Runnable()
{
@Override
public void run()
{
a.add();
}
});
t2.start();
t1.start();
}
}
执行结果
当前线程是: Thread-0 before a=0 after a=1
当前线程是: Thread-1 before a=1 after a=2
注: synchronized (obj){} obj是能是对象,基本数据类型需改为封装数据类型才能使用
volatile
保持变量在多线程的可见性,NO原子性,不能解决并发问题
Lock
可以解决并发问题,原理就是 volatile + 乐观锁,必须手动释放锁,而synchronized 是jvm控制释放锁,包括异常时也是jvm释放锁,而Lock只能自己释放,所以强制使用try{}finally{} finally来释放锁
ThreadPoolExecutor
线程池