线程的创建
1.继承Thread,重写run方法
MyThread01 myThread01=new MyThread01();
// myThread01.start();//同时开始,交替执行
myThread01.run();
2.实现Runnable接口
TestThread02 testThread02=new TestThread02();
Thread thread =new Thread(testThread02);
thread.start();
3.实现Callable接口(不重要),重写call方法(需要关闭服务)有返回值,布尔类型
ExecutorService
Executors
程序:是指令和数据的有序集合
进程:是程序执行的一次过程
线程:进程是包含多个线程,一个进程最起码有一个线程,
用start方法,线程不一定立即执行,由CPU调度执行。
多个线程同时操作一个对象(用实现Runnable接口)
lambda 表达式在简化时只能简化有一行代码的,还得是函数式接口,只有一个方法
Ilike ilike = a -> System.out.println("i like"+a);
Ilike ilike =(a,b) -> System.out.println("i like"+a);
Ilike ilike =( int a) -> System.out.println("i like"+a);
线程的状态
创建(new)->就绪(start)->阻塞(sleep,wait)->运行->死亡(dead)
建议线程正常停止,不要使用stop,destroy等方法
礼让
Thread.yield();//礼让
强制执行
thread.join();//线程强制加入,会使其他线程阻塞
线程的状态监测
Thread.getState()//获取线程的状态
while (state != State.TERMINATED)//线程不死就一直跑
线程一旦死亡,不可再start
线程优先级
Thread.currentThread().getPriority()
Thread.currentThread().setPriority()
守护线程
线程分为用户线程和守护线程。
thread.setDaemon(true);//设置为守护线程,默认为false
//即使守护线程可以一直执行,但如果要守护的线程已经死亡,他也会完后自己使命后死亡
//该设置仅在Thread处于NEW状态时候设置有效,不能在线程启动之后设置。如果设置则会抛出异常 IllegalThreadStateException 。
线程同步
实际上是一种等待机制
线程同步条件:(队列加锁)
synchronized方法,锁的是本身,synchronized块锁的是对象
缺陷:当锁的方法过大时,会影响效率。
死锁
两个或多个线程都在对方等待释放资源,就会产生停止执行现象,某一个同步块同时拥有两个以上对象的锁就会产生死锁现象
lock锁
可重入锁,
ReentrantLock lock=new ReentrantLock();//定义锁
try{
lock.lock();//锁定
}
finally {
lock.unlock();//解除锁定
}
死锁产生的四个必要条件
- 互斥: 某种资源一次只允许一个进程访问,即该资源一旦分配给某个进程,其他进程就不能再访问,直到该进程访问结束。
- 占有且等待: 一个进程本身占有资源(一种或多种),同时还有资源未得到满足,正在等待其他进程释放该资源。
- 不可抢占: 别人已经占有了某项资源,你不能因为自己也需要该资源,就去把别人的资源抢过来。
- 循环等待: 存在一个进程链,使得每个进程都占有下一个进程所需的至少一种资源。
Lock与synchronized有以下区别:
- Lock是一个接口,而synchronized是关键字。
- Lock可以让等待锁的线程响应中断** lock.trylock() **,而synchronized不会,线程会一直等待下去。
- 通过Lock可以知道线程有没有拿到锁** lock.holdlock() **,而synchronized不能。
- Lock能提高多个线程读操作的效率。
- synchronized能锁住类、方法和代码块,而Lock是块范围内的
管程法:生产者到消费者可以提供一个缓冲器,生产者把数据放到缓冲区中,然后让消费者去拿
信号灯法:通过标志位来解决
this.notifyAll:通知唤醒
线程池
好处:
- 提高响应速度;
- 降低资源消耗;
- 便于线程管理。
//创建服务,设置线程池大小
ExecutorService executorService = Executors.newFixedThreadPool(10);