- 线程简介
- 任务:指具体做某一些事(列如写代码,玩手机,打游戏等等)
- 线程(Thread):一个进程好比一棵树,树的分支就是线程(列如微信,聊天,电话,视频)
- 进程(Process):运行的程序就是进程(列如,打开某一个软件,运行一个程序,就是开一个进程)
- 多线程:同一时间执行多条任务,分工明确(列如一个团队分工开发项目一样)
- GCC:垃圾回收
- 线程实现(重点)
Thread Runable Callable
线程创建
- 继承Thread
备注:test.start()异步执行 test.run()同步执行
- 实现Runable
public class RunableImplTest implements Runnable{
@Override
public void run() {
System.out.printf("我是Runale的run方法");
}
public static void main(String[] args) {
Thread thread=new Thread(new RunableImplTest());
thread.start();
System.out.printf("我是主体方然");
}
}
备注:通过构造参数传递累对象来实现
- 实现Callable接口
public class CallableImplTest implements Callable<Boolean> {
@Override
public Boolean call() throws Exception {
System.out.println("call");
return true;
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
//创建线程池
ExecutorService ser=Executors.newFixedThreadPool(3);
//指定需要执行的线程
Future<Boolean> result1=ser.submit(new CallableImplTest());
//获取结果
boolean result=result1.get();
//关闭服务
ser.shutdownNow();
System.out.println("result:"+result);
}
}
备注:可以获取线程执行后的结果,需要返回值时使用,抛出异常
- 线程不安全
- 多线程操作同一个对象,会造成数据错乱
- Lamda表达式
- 为什么要使用Lamda表达式
- 避免匿名内部内过多
- 可以让你的代码看起来更简洁
- 去掉一堆没有意义的代码,留下核心的代码
- 也许你会说,我看了Lamda表达式,但不觉得简洁,反而有些混乱,看不懂,那是因为我们还没有习惯,用多了就好了
- Lamda表达式
public class LamdaTest {
/**
* 静态类部类
*/
@Slf4j
static class LamdaHyappy2Impl implements LamdaHyappy{
@Override
public void lamdaHyappy() {
log.info("我是静态类部类lamdaHyappy2");
}
}
public static void main(String[] args) {
//常规实现
LamdaHyappy lamdaHyappy1=new LamdaHyappy1Impl();
lamdaHyappy1.lamdaHyappy();
//静态类部类
LamdaHyappy lamdaHyappy2=new LamdaHyappy2Impl();
lamdaHyappy2.lamdaHyappy();
//局部类部类
// @Slf4j
// class LamdaHyappy3Impl implements LamdaHyappy{
//
// @Override
// public void lamdaHyappy() {
// log.info("我是局部类部类");
// }
// }
// LamdaHyappy lamdaHyappy3=new LamdaHyappy3Impl();
// lamdaHyappy3.lamdaHyappy();
//匿名类部类
lamdaHyappy1 = () -> {
System.out.println("sddsdsd");
};
}
}
interface LamdaHyappy{
void lamdaHyappy();
}
@Slf4j
class LamdaHyappy1Impl implements LamdaHyappy{
@Override
public void lamdaHyappy() {
log.info("我是lamdaHyappy1");
}
}
备注:任何接口如果只包含唯一的一个抽象方法,那么他就是一个函数式接口
- 线程状态
线程停止:不建议使用jdk提供的stop,和destor方法停止线程【已经废弃】
推荐线程自动停止下来
建议使用一个标志来控制线程是否停止
1、线程休眠
- Sleep(线程)指当前运行前线程阻塞的毫秒
- Sleep存在异常InterruptedExecption
- Sleep时间达到后线程进入就绪状态
- Sleep可以模拟网络延时,倒计时等
- 每个对象都会有一个锁,sleep不会释放锁
线程安全可以放大发现性
- 线程礼让
- 礼让线程,让当前正在执行的线程暂停,但不阻塞
- 将线程运行时状态转为就绪状态
- 让CUP重新调度,礼让不一定成功,看cup心情
- Join
- Join合并线程,待此线程执行完毕后,再执行其他线程,其他线程阻塞
- 可以理解为插队
- 线程状态观测
Thread.State
线程状态,线程可以处于的状态之一
-
- .NEW 尚未启动的线程处于此状态
- .RUNNABLE 在Java虚拟机中执行线程处于此状态
- .BLOCKED 被阻塞等待监视器锁定执行的线程处于此状态
- .WAITING 正在等待宁一个线程特定动作的线程处于此状态
- .TIED_WAITING 正在等待宁一个正在执行的动作达到指定等待时间的线程处于这种
- .TERMINATED 已退出线程处于此状态
一个线程可以在给定的时间点处于一个1,这些状态是不反映任何操作系统线程状态的虚拟机状态;
- 线程优先级
- Java提供一个线程调度器来监听程序中启动后进入一个就绪状态的所有线程,线程 调度安装优先级决定应该调用那个线程来执行
- 线程的优先级用数字标识,范围从1~100
- Thread.MIN_PRIORITY=1;
- Thread.MAX_PRIORITY=10;
- Thread.NORM_PRIORITY=100;
- 使用一下方式改变获取优先级
- getPriority() setPriority(int x)
- 守护线程
- 线程分为用户线程和守护线程
- 虚拟机必须确保用户执行完毕
- 虚拟机不用等待守护线程执行完毕
- 如果后台记录操作日志,监控内存,垃圾回收等待
- 线程同步(重点)
- 并发,同一个对象被多个线程调用(在程序中就是队列,或者可以说是同步)
- 由于同一个进程共享一块存储空间,在带来方便的同事,也会带来访问冲突问题,为了保证数据在方法中呗访问的正确性,在访问是加上”锁机制synchronized”,当一个线程获取对象的锁,他独占资源,其他线程必须等待,使用后释放锁即可
使用锁存在以下几个问题:
- 一个线程持有锁会导致其他所有需要次线程的线程挂起,也就是排队
- 在多线程竞争下,加锁,释放锁会导致比较多的上下切换 好调用延时,引起性能问题
- 如果一个优先级搞得线程等待一个优先级低的线程释放锁会导致优先级倒置,引发性能问题
- 线程死锁、
- Lock锁
八、 Synchronized与Lock的对比
- Lock是显式锁(手动开启手动关闭锁,别忘记关闭锁)synchronized是隐式锁,出来作用于自动释放锁
- Lock只有代码锁,synchronized有代码块和方法锁
- 使用Lock锁,JVM将花费较少的时间来调度线程,性能更好。并且具有更好的扩展性(提供更多的子类)
- 优先顺序:
- Lock > synchronized(已经进入了方法体,分配了相应资源)>同步方法 (在方法体之外)
- 线程池
背景:经常创建和销毁,使用量特别大的资源,比如并发的情况下线程,对性能影响很大。
思路:提前创建好多个线程,放入线程池中,使用时直接获取,使用完毕放回池中
可以避免频繁创建和销毁,实现复用利用,类似生活中的交通工具;
好处:
- 提高响应速度 (减少创建新线程的时间)
- 降低资源消耗(重复利用·线程池中线程,不需要每次都创建)
- 便于线程管理(....)
- corePoopSize: 核心池大小
- maximumPoolSize:最大线程数
- keepAliveTime:线程没有任务时最多保持多长时间后终止
使用线程池
- JDK 5.0 起提供了线程池相关API:ExecutorService 和Executors
- ExecutorService:真正的线程池接口,常见子类 ThreadPoolExecutor
- Void execute(Runnable command) : 执行任务/命令 ,没有返回值,一般用来执行 Runable
- <T> Future<T> submit(Callable<T> task):执行任务,有返回值,一般用来执行Callable
- Void shutdown():关闭线程池
- Executors:工具类,线程池的工厂类,同于创建并返回不通的线程此
public class PoolTest {
public static void main(String[] args) {
PollThread pollThread=new PollThread();
ExecutorService service= Executors.newFixedThreadPool(10);
service.execute(new PollThread());
service.execute(new PollThread());
service.execute(new PollThread());
service.execute(new PollThread());
service.execute(new PollThread());
service.execute(new PollThread());
service.execute(new PollThread());
service.execute(new PollThread());
service.execute(new PollThread());
service.execute(new PollThread());
//关闭连接
service.shutdown();
}
}
class PollThread implements Runnable{
int count=0;
@Override
public void run() {
count++;
System.out.println("第"+count+"条线程此:"+Thread.currentThread().getName());
}
}