廊坊网站建站网站,wordpress微信 群发,wordpress批量注册用户,南昌vr网站开发文章目录 一、概念1、进程2、线程3、CPU与线程的关系4、并行、并发5、线程的生命周期 二、创建1、继承Thread2、实现Runnable接口3、实现Callable接口 三、API1、获取运行使用的线程2、唯一标识3、线程名4、优先级5、是否处于活动状态6、守护线程7、join1、API2、有无join对比 … 文章目录 一、概念1、进程2、线程3、CPU与线程的关系4、并行、并发5、线程的生命周期 二、创建1、继承Thread2、实现Runnable接口3、实现Callable接口 三、API1、获取运行使用的线程2、唯一标识3、线程名4、优先级5、是否处于活动状态6、守护线程7、join1、API2、有无join对比 8、yield9、sleep10、线程中断 一、概念
1、进程
进程就是正在运行中的程序
2、线程
是1个进程程序内部的1条执行路径单线程1个进程中只有1个线程1条执行路径多线程1个进程中包含多个线程多条执行路径线程之间堆内存、方法区内存共享但是栈内存独立1个线程一个栈
3、CPU与线程的关系
单核CPU不能够做到真正的多线程并发因为在一个时间单元内只能执行一个线程的任务多个线程谁获取时间片运行谁每个线程获取时间片的概率相等可能t1、t2、t2、t2给人一种多线程并发的感觉其实是由于CPU的处理速度极快多个线程之间频繁切换执行跟人来的感觉是多个事情同时在做
4、并行、并发
并行多核CPU同时执行多个任务。比如多个人同时做不同的事并发单核CPU同时执行多个任务。比如多个人做同一件事
5、线程的生命周期
新建状态 新建了线程对象还没调用start方法 就绪状态 线程调用了start方法等待获取CPU时间片表示当前线程具有抢夺CPU时间片的权力 运行状态 线程对象开始执行run方法run方法的开始执行标志着这个线程进入运行状态当之前占有的CPU时间片用完之后会重新回到就绪状态继续抢夺CPU时间片当再次抢到CPU时间之后会重新进入run方法接着上一次的代码继续往下执行 阻塞状态 当一个线程遇到阻塞事件例如sleep方法、获取synchronized排他锁失败(因为锁被其它线程所占用)等此时线程会进入阻塞状态阻塞状态的线程会放弃之前占有的CPU时间片之前的时间片没了需要再次回到就绪状态抢夺CPU时间片 死亡状态 run方法执行完毕或者因异常退出了run方法该线程生命周期结束
二、创建
1、继承Thread
class Thread implements Runnable缺点 由于java是单继承的这导致继承了Thread后就不能在继承其它类了在实际开发中会经常继承某个超类来复用其中的方法这导致两者不能同时继承继承线程后重写run方法来定义任务这又导致我们将任务直接定义在线程上使得线程只能做该任务无法并发执行其他任务重用性变差
public class HandleMsg extends Thread{/** 线程标识 */private String threadKey;/** 构造方法用来区分不同线程便于测试 */public HandleMsg(String threadKey){this.threadKeythreadKey;}Overridepublic void run(){for(int i0;i10;i){System.err.println(threadKeyrun);}}}//匿名内部类lambda
Thread t1new Thread(()-{for(int i0;i10;i) {System.err.println(t1run);}
};//创建2个线程对象
HandleMsg h1new HandleMsg(h1);
HandleMsg h2new HandleMsg(h2);//启动线程开始执行实现的run方法
h1.start();
h2.start();2、实现Runnable接口
优点线程和线程执行的任务分离
public class HandleMsg implements Runnable{/** 线程标识 */private String threadKey;/** 构造方法用来区分不同线程便于测试 */public HandleMsg(String threadKey){this.threadKeythreadKey;}Overridepublic void run(){for(int i0;i10;i){System.err.println(threadKeyrun);}}}//创建2个任务对象
HandleMsg h1new HandleMsg(h1);
HandleMsg h2new HandleMsg(h2);//将任务1交给线程1
Thread t1new Thread(h1);
//将任务2交给线程2
Thread t2new Thread(h2);//启动线程开始执行任务的run方法
t1.start();
t2.start();3、实现Callable接口
FutureTask implements RunnableFutureRunnableFutureV extends Runnable优点 线程和线程执行的任务分离有返回值可以声明抛出的异常
//Callable的泛型就是重写的call方法的返回值类型
public class HandleMsg implements CallableString{/** 线程标识 */private String threadKey;/** 构造方法用来区分不同线程便于测试 */public HandleMsg(String threadKey){this.threadKeythreadKey;}Overridepublic String call() throws Exception{for(int i0;i10;i){System.err.println(threadKeyrun);}return threadKey;}}//创建2个任务对象
HandleMsg h1new HandleMsg(h1);
HandleMsg h2new HandleMsg(h2);//创建FutureTask类包装任务对象泛型就是任务类实现Callable的泛型也就是call方法返回值的类型
FutureTaskString f1new FutureTask(h1);
FutureTaskString f2new FutureTask(h2);//将FutureTask对象交给线程
Thread t1new Thread(f1);
Thread t2new Thread(f2);//启动线程开始执行任务的run方法
t1.start();
t2.start();//获取返回值
String result1f1.get();
String result2f2.get();三、API
1、获取运行使用的线程
//在哪个方法执行就获取执行该方法的线程
Thread threadThread.currentThread();2、唯一标识
long getId();3、线程名
String getName();//线程启动之前可以设置线程名
void setName(String name);4、优先级
线程有10个优先级用1-10表示默认为5
int getPriority();//启动之前设置
//线程无法主动获取cpu时间片唯一可以干涉线程调度工作的方式就是修改线程的优先级最大程度的改善获取cpu时间片的几率理论上线程优先级越高的线程获取cpu时间片的次数越多
void setPriority(int newPriority);5、是否处于活动状态
boolean isAlive();6、守护线程
守护线程又称为后台线程默认创建出来的线程都是普通线程或称为前台线程当进程结束时所有正在运行的守护线程都会被强制中断进程的结束当一个进程中没有任何前台线程时即结束main主线程就是前台线程不受其他线程影响分配其他线程后接着干自己的事其他线程执行的时候main线程可能已经结束了
//是否为守护线程
boolean isDaemon();//启动之前设置
void setDaemon(boolean on);7、join
作用是让当前执行的线程陷入等待内部调用了wait方法。 永久等待其实现原理是不停的检查当前线程是否存活该线程的任务执行完毕后就会处于死亡状态如果存活则说明任务还未执行完毕-继续等待 线程启动之后调用
1、API
//等待线程执行完任务后再往下执行join(0);
void join();//等待线程执行一段时间后再往下执行无论线程任务是否执行完毕单位毫秒
void join(long millis);2、有无join对比
//1、程序正常运行顺序是不会等待线程任务执行完毕就会往下执行
Thread t1new Thread(()-{for(int i0;i5;i){System.err.println(i);}
});
t1.start();System.err.println(next task);// 输出结果
// next task
// 0
// 1
// 2
// 3
// 4//2、调用join
Thread t1new Thread(()-{for(int i0;i5;i){System.err.println(i);}
});
t1.start();t1.join();System.err.println(next task);// 0
// 1
// 2
// 3
// 4
// next task8、yield
线程让步暂停不是终止当前正在执行的线程任务让其它具有相同优先级或更高优先级的等待的线程执行任务其它也会包含暂停的线程所以有可能刚暂停就执行暂停的线程状态变化运行状态 - 就绪状态暂停期间不会释放锁所以其他线程获取不到锁
9、sleep
使线程睡眠sleep的睡眠期间不会释放锁所以其它线程获取不到锁睡眠线程的状态变化运行状态 - 阻塞状态 - 就绪状态
//Thread的静态方法单位毫秒
static void sleep(long millis) throws InterruptedException;sleep和wait的区别
sleepwait属于Thread类属于Object类可以在任何地方使用wait、notify、notifyAll 只能在同步方法、同步控制块里面使用睡眠期间不会释放锁会释放锁而且会将当前线程加入到等待队列中不需要唤醒可以被notify、notifyAll唤醒
10、线程中断
只是打断线程的睡眠不会终止线程的继续执行
//线程是否中断
boolean isInterrupted();//中断线程睡眠
Thread t1new Thread(()-{System.err.println(run......);try{//睡眠10sThread.sleep(10000L);}catch(InterruptedException e){e.printStackTrace();}System.err.println(end......);
});//启动线程
t1.start();//中断睡眠
//线程不会睡眠10s而是被中断抛出InterruptedException捕获该异常后继续执行后续的代码
t1.interrupt();System.err.println(next task);// 执行结果
// next task
// run......
// end......