线程的创建方式
- 继承Thread 类(只有一个线程)
1.重写Run方法(线程要执行的内容),
2.创建对象调用start方法(启动线程开始执行,调用Run方法)
发现运行结果不同:多个线程抢夺 cpu 多线程的随机性 在某一个时刻只能有一个线程在运行(多核除外) 获取线程的名称Thread. currentThread().getName()
- 实现 Runnable 接口的类(拓展角度推荐使用)
1.实现 Runnable 接口(run方法没有办法抛出异常)
2.重写Runable接口中的run方法 子类对象作为参数传入Thread构造方法
3.创建Thread类
4.调用Thread类中的start方法 真正的线程是Thread,或者是Thread子类
- 实现Callable接口(重写的方法有返回值,可以抛出异常)
和Runnable 接口相似
1.FutureTask 接口 将Callable对象进行包装 包装为Runnable子类,方便我们创建线程,传入参数
2.通过call方法 得到的返回值需要使用FutureTask的get方法获得
- Runnable和Callable区别:
- 都是接口,都可以用来创建线程
- Callable和Runnable都可以用于线程池
- Callable 的call方法可以返回一个类型 Ruannable没有返回值
- Callable 的call方法可以抛出异常,Runnable的run方法不能抛出异常
- Callable 1.5 Runnable 1.0
Synchronized
- 同步的三个前提:
必须是两个或者两个以上的线程同时操作一个资源
- 锁的唯一性
同步代码块的锁可以是任意对象
同步方法的锁是this关键字
静态同步方法地锁是类名.class 就是累的字节码文件
- 同步的好处和弊端:
好处:解决了多线程并发访问的安全问题
弊端:多了一个判断锁的动作,消耗了内存
- 线程间的通信:
多个线程操作同一个资源,但是操作的动作不同
Thread 类中的其他方法:
- 线程结束:
1.让循环结束
2.interrupt 中断线程
- 守护线程(后台线程):
void setDaemon(boolean on)
将该线程标记为守护线程或用户线程。 必须在线程启动之前使用 当所有前台线程结束后,后台线程自动结束
- 加入线程
void join()
等待该线程终止。 插队
void join(long millis)
等待该线程终止的时间最长为 millis 毫秒 当前线程暂停 当指定线程结束时,当前线程继续执行
- 注意:
jdk规定join(0)的意思不是等待0毫秒后,其他线程可以继续,而是 等价于join();
join方法必须在线程start方法调用之后才有意义
- 线程优先级:
void setPriority(int newPriority)
更改线程的优先级 最高是10,默认是5
- 礼让线程:
static void yield()
暂停当前正在执行的线程对象,并执行其他线程
线程池;
- 无界限线程池 可自动回收线程
static ExecutorService newCachedThreadPool(ThreadFactory
threadFactory)
创建一个可根据需要创建新线程的线程池,但是在以前构造的线程可用时将重用它们,并在需要时使用提供的 ThreadFactory 创建新线程
- 固定大小线程池
static ExecutorService newFixedThreadPool(int nThreads)
创建一个可重用固定线程数的线程池,以共享的无界队列方式来运行这些线程。
- 固定大小 可根据时间启动线程池
static ScheduledExecutorService newScheduledThreadPool(int
corePoolSize)
创建一个线程池,它可安排在给定延迟后运行命令或者定期地执行。
- 单线程线程池
static ExecutorService newSingleThreadExecutor()
创建一个使用单个 worker 线程的 Executor,以无界队列方式来运行该线程。