Day05-多线程
多线程
多线程的创建方式:
方式一:继承于Thread类
- 创建一个继承于Thread类的子类
- 重写Thread类的run() --> 将此线程执行的操作写在run()方法里面
- 创建Thread类的子类的对象
- 通过此对象调用start():启动当前线程;调用当前线程的run()
我们不能通过直接调用run()的方式启动线程
再启动一个线程,不可以还让已经start()的线程去执行.会报Illegalthreadexception,需要重新创建一个线程的对象
创建Thread类的匿名子类的方法
Public class ThreadDemo(){
new Thread(){
@override
public void run(){
}
}.start();
}
Thread中的常用方法:
- start(): 启动当前线程;调用当前线程的run()
- run(): 通常需要重写Thread类中的方法,将创建的线程要执行的操作声明在此方法中
- currentThread(): 静态方法,返回执行当前代码的线程
- getName(): 获取当前线程的名字
- setName(): 设置当前线程的名字
- yield(): 释放当前CPU的执行权
- join(): 在线程a中调用线程b的join(),此时线程a就进入阻塞状态,直到线程b完全执行完以后,线程a才结束阻塞状态
- stop(): 已过时.强制结束线程生命期
- sleep(long millitime): 让当前线程"睡眠"指定的millitime毫秒.在指定的millitime毫秒时间内,当前线程是阻塞状态
- isAlive(): 判断当前线程是否存活
方式二:实现Runnalbe接口
- 创建一个实现了Runnalbe接口的类
- 实现类去实现Runnable中的抽象方法:run()
- 创建实现类的对象
- 将此对象作为参数传递到Thread类的构造器中,创建Thread类的对象
- 通过Thread类的对象调用start()-->启动线程;调用当前线程的run():调用了Runnable类型的target的run()方法
class MThread implements Runnable(){
@override
public void run(){
............
}
}
public class Threadtest{
public static void main(String[] args){
MThread mThread = new MThread();
Thread t1 = new Thread(mThread);
t1.start();
}
}
//匿名对象的创建
new Thread(new runnable()){
@override
public void run(){
}
}
线程的优先级:
- MAX_PRIORITY:10
- MIN_PRIORITY:1
- NORM_PRIORITY:5 --默认的优先级
如何设置线程的优先级
getPriority():获取线程的优先级
setPriority(int p:)设计线程的优先级
说明:高优先级的线程要抢占低优先级线程cpu的执行权.但是只是从概率上讲,高优先级的线程高概率的情况下被执行,并不意味着只有当高优先级的线程执行完以后,低优先级的线程才执行.
两种创建方式的对比
开发中,优先选择:实现Runnable接口的方式
原因1. 实现的方式没有类的单继承性的局限性
2. 实现的方式更适合来处理多个线程有共享数据的情况
联系:public class Thread implements Runnable
相同点:两种方式都需要重写run(),将线程要执行的逻辑声明在run()中.
方式三:实现Callable接口 - - JDK 5.0新增
//1.创建一个实现Callable的实现类
class NumThread implements Callable{
//2.实现call方法,将次线程需要执行的操作声明在call()中
@override
public Object call() throws Exception{
}
}
public class ThreadNew{
NumThread numThread = new NumThread()
//3.创建Callable接口实现类的对象
FutreTask futureTask = new FutureTask(numThread);
//4.将此Callable接口实现类的对象作为传递到FutreTask构造器中,创建FutreTask的对象
new Thread(futureTask).start();
//5.将FutureTask的对象作为参数传递到Thread类的构造器中,创建Thread对象,并调用start()
try{
//.6
//get()返回值即为FutureTask构造器参数Callable实现类重写的call()的返回值.
futureTask.get();
.........
}catch(InerruptedException e){
}catch(ExecutionException e){
}
}
问题:如何理解实现Callable接口的方式创建多线程比实现Runable接口创建接口方式强大?
- call()可以有返回值的.
- call()可以抛出异常,被外面的操作捕获,获取异常的信息
- Callable是支持泛型的
方式四:使用线程池
好处:
- 提高响应速度(减少了创建新线程的时间)
- 降低资源消耗(重复利用线程池中线程,不需要每次都创建)
- 便于线程管理
corePoolSize:核心池的大小
maximumPlloSize:最大线程数
keepAliveTime:线程没有任务时最多保持多长时间后会终止
class NumberThread implements Runnable{
@override
public void run(){
}
}
class NumberThread1 implements Runnable{
@override
public void run(){
}
}
public class ThreadPool{
public static void main(String[] args){
//1. 提供指定线程数量的线程池
ExecutorService service = Executors.newFixedThreadPool(nThread:10);
ThreadPoolExecutor service1 = (ThreadPoolExecutor) service;
//设置线程池的属性
//System.out.println(service.getClass())
service1.setcorePoolSize(15);
//service1.setKeepAliveTime();
//2. 执行指定的线程的操作.需要提供实现Runnable接口或Callable接口实现类的对象
service.execute(new NumberThread());//适合适用于Runnable
service.execute(new NumberThread1());
//ervice.submit(Callable callable);//适合适用于Callable;
//关闭连接池
service.shutdown;
}
}