- 如何开启线程
开启线程2种方式:
自定义类继承Thread类,重写run方法;new 自定义类().start()
自定义类实现Runnable接口,实现run方法;new Thread(new 自定义类()).start()
- Thread和Runable
Thread是对线程的抽象封装,完成独立完成某个任务的调度,包括任务的开始、暂停、结束等操作。本身是实现Runnable接口,所以具有Runnable的所有功能。
Runnable 是对任务的抽象封装,业务任务的具体逻辑封装。本身不具有独立资源调度。需要Thread协助完成,这也就是前面说的开启线程需要先new Thread() 通过参数把Runnable传递进去。
- JVM开启,默认开启哪些线程(JDK1.8为例)
public static void main(String[] args) {
//虚拟机线程系统的管理接口(JVM开启的线程);对JVM系统进行监控时,使用类ManagementFactory
ThreadMXBean threadMXBean= ();
ThreadInfo[] threadInfos = (false, false);
for(ThreadInfo threadInfo:threadInfos){
("["+()+"]"+());
}
/* 一般项目启动会启动的线程有:
* [8]JDWP Command Reader
[7]JDWP Event Helper Thread
[6]JDWP Transport Listener: dt_socket
[5]Attach Listener
[4]Signal Dispatcher
[3]Finalizer 线程管理Object finalize()方法,每个对象销毁时都会调用这个方法;不推荐在这个方法中写资源释放,有时调用不到(main结束这个线程也就没有了)
[2]Reference Handler
[1]main 主线程,线程关闭其他线程会依次关闭
* */
}
- stop/interrupt/sleep等方法总结
stop():结束线程,比较野蛮会立即结束线程。比如当前线程正在写一个文件,或者正在写入数据库,正在完成一半任务时,接到stop命令,立即线程结束,导致文件不完整,错误的文件或数据库数据不完整等问题。所以JDK1.8之后不在推荐使用。当然如果能够保证当前线程没有这些类似任务,采用stop停止线程也是可以的。
interrupt():标记线程状态为中断状态(线程本身并不会结束),此时线程中如果有join、wait、sleep等方法调用的时候会抛出异常。在线程的run()方法中我们需要自己写逻辑结束线程。isInterrupt()可获取线程的中断状态。()静态方法内部会调用当前线程的isinterrupt()方法,但是内部也会再次把状态标志位修改,所有一般都是用实例interrupt方法。对于Runnable实例化的线程,一般用().interrupt() 方法判断。
sleep():使当前线程进入阻塞状态。同时这个方法内部会监测interrupt状态,如果当前线程中断后,同时线程还睡眠时,会报异常: sleep interrupted。sleep()并不会释放对象锁,只有锁代码块执行完后,其他线程才能够获取锁。
- 线程stop方法案例
import ;
/**
* @ClassName xu01
* @Description des
* @Author zyk
* @Date 2019/9/24
* @Version 1.0
**/
public class xu01 {
private static class UseThread extends Thread{
@Override
public void run() {
while(true) {
("正在写入文件,写入部分...");
}
}
}
public static void main(String[] args) {
UseThread useThread=new UseThread();
();
//main线程睡眠20
try {
(20);
} catch (InterruptedException e) {
();
}
//main线程2秒后关闭
// 1:stop() 是一个@Deprecated不推荐使用,过于野蛮停止线程(会出现线程写部分文件就挂了)
();
("main 线程结束");
}
}
- 线程interrupt方法案例
import ;
/**
* @ClassName xu01
* @Description des
* @Author zyk
* @Date 2019/9/24
* @Version 1.0
**/
public class xu01 {
private static class UseThread extends Thread{
@Override
public void run() {
while(true) {
("正在写入文件,写入部分...");
//判断线程状态是否,是否需要结束
// if(isInterrupted()){
//静态方法也是同样的功能,内部会获取当前线程
if(()){
("线程状态:"+interrupted());
("判断当前文件写完了,然后结束线程,不会导致文件是个损坏的文件");
break;
}
}
}
}
public static void main(String[] args) {
UseThread useThread=new UseThread();
();
//main线程睡眠20
try {
(20);
} catch (InterruptedException e) {
();
}
//main线程2秒后关闭
//只是标记线程标志位为中断状态,需要在run方法中写逻辑结束线程,否则线程还是不能够结束
();
("main 线程结束");
}
}
- 线程sleep方法案例
在线程中添加sleep睡眠逻辑,做完一件事后睡眠一段时间,再次做事情。
import ;
/**
* @ClassName xu01
* @Description des
* @Author zyk
* @Date 2019/9/24
* @Version 1.0
**/
public class xu01 {
private static class UseThread extends Thread{
@Override
public void run() {
while(true) {
("正在做某件任务...");
("结束一段任务后,线程睡眠一段时间");
try {
(20);
} catch (InterruptedException e) {
();
}
if(()){
("线程状态:"+interrupted());
("判断当前文件写完了,然后结束线程,不会导致文件是个损坏的文件");
break;
}
}
}
}
public static void main(String[] args) {
UseThread useThread=new UseThread();
();
//main线程睡眠20
try {
(20);
} catch (InterruptedException e) {
();
}
//main线程2秒后关闭
//只是标记线程标志位为中断状态,需要在run方法中写逻辑结束线程,否则线程还是不能够结束
();
("main 线程结束");
}
}
注意:这样线程并不会结束,运行结果如下
正在做某件任务...
结束一段任务后,线程睡眠一段时间
: sleep interrupted
at (Native Method)
at (:340)
at (:386)
at .xu01$(:21)
main 线程结束
正在做某件任务...
结束一段任务后,线程睡眠一段时间
正在做某件任务...
结束一段任务后,线程睡眠一段时间
这是因为 (20);会抛出异常后,把当前线程中断状态又改回去了,导致线程还会继续执行。
需要修改代码:第一种方式,在sleep方法上添加try-catch,在InterruptedException异常代码块中再次调用interrupte()方法。第二种方式,把while死循环监视起来,出现InterruptedException 异常后结束线程,修改后代码如下:
import ;
/**
* @ClassName xu01
* @Description des
* @Author zyk
* @Date 2019/9/24
* @Version 1.0
**/
public class xu01 {
private static class UseThread extends Thread{
@Override
public void run() {
try {
while (true) {
("正在做某件任务...");
("结束一段任务后,线程睡眠一段时间");
try {
(20);
//: sleep interrupted 需要把这个异常抛出去
} catch (InterruptedException e) {
//interrupt();
throw e;
}
if (()) {
("线程状态:" + interrupted());
("判断当前文件写完了,然后结束线程,不会导致文件是个损坏的文件");
break;
}
}
}catch (InterruptedException e){
();
("子线程结束");
}
}
}
public static void main(String[] args) {
UseThread useThread=new UseThread();
();
//main线程睡眠20
try {
(20);
} catch (InterruptedException e) {
();
}
//main线程2秒后关闭
//只是标记线程标志位为中断状态,需要在run方法中写逻辑结束线程,否则线程还是不能够结束
();
("main 线程结束");
}
}
- 线程池使用
JDK1.8不在推荐使用Executors创建线程了,推荐使用ThreadPoolExecutor,可控制最大线程数量。而Executors 最多创建线程数量是 Integer.MAX_VALUE 会导致系统OOM问题。
public static void main(String[] args) throws ExecutionException, InterruptedException {
int count=230;
//线程池1:
ExecutorService pool1=();
ExecutorService pool2=(5);
//线程池2:
ThreadFactory namedThreadFactory=new ThreadFactoryBuilder()
.setNameFormat("jake-pool-%d")
.build();
ExecutorService pool=new ThreadPoolExecutor(5,200,
60L,,new LinkedBlockingQueue<Runnable>(1024),
namedThreadFactory,new ());
for(int i=0;i<count;i++){
(()->{
("========线程名称:"+().getName());
});
}
();
("shutdown");
}