多线程的两种方式实现方法:1.thread 2.runnable
两种方式的比较:
Runnable方式可以避免thread方式由于java单继承特性带来的缺陷
Runnable的代码可以被多个线程(thread实例)共享,适合于多个线程处理同一资源的情况
线程的生命周期:
创建——就绪——阻塞——运行——终止
创建:调用start方法到就绪状态。
就绪:创建了线程对象后,调用了线程的start()方法(注意:此时线程只是进入了 线程队列,等待获取CPU服务,具备了运行的条件,但并不一定已经开始运行了)获取cup才进入运行状态。
阻塞:一个正在执行的线程在某些情况下,由于某种原因而暂时让出了CPU资源,暂停了自己的执行,便进入了阻塞状态,如调用了sleep方法。从而让其他资源执行。
终止:线程的run()方法执行完毕,或者线程调用了stop()方法,线程便进入终止状态。
Java线程有两类:
用户线程:运行在前台。
守护线程:运行在后台,为其他前台线程服务。有人这么解释:所谓的守护现成也只是相对的,没有什么神奇的地方,也就是一个线程摆了。 就好比是一个大官,旁边跟着一个报表,防止大官摔着了什么的。
特点:一旦所有用户线程都结束运行,守护线程会随JVM一起结束工作
应用:数据库连接池中的监测线程
JVM虚拟机启动后的监测线程
最常见的是:垃圾回收线程
如何设置?
举个例子:
看代码:
1 import java.io.File; 2 import java.io.FileOutputStream; 3 import java.io.OutputStream; 4 import java.util.Scanner; 5 6 7 class DeamonThread implements Runnable{ 8 9 @Override 10 public void run() { 11 System.out.println("进入守护线程"+Thread.currentThread().getName()); 12 13 try { 14 writeToFile(); 15 } catch (Exception e) { 16 e.printStackTrace(); 17 } 18 System.out.println("退出守护线程"+Thread.currentThread().getName()); 19 } 20 21 private void writeToFile() throws Exception{ 22 File filename=new File("d:"+File.separator+"daemon.txt"); 23 OutputStream os=new FileOutputStream(filename, true); 24 int count=0; 25 while(count<999){ 26 os.write(("\r\nword"+count).getBytes()); 27 System.out.println("守护线程"+Thread.currentThread().getName()+ 28 "向文件中写入word"+count++); 29 Thread.sleep(1000); 30 31 } 32 } 33 34 35 } 36 37 public class DeamonThreadDemo { 38 39 /** 40 * @param args 41 */ 42 public static void main(String[] args) { 43 System.out.println("进入线程"+Thread.currentThread().getName()); 44 DeamonThread d=new DeamonThread(); 45 Thread t=new Thread(d); 46 //手工暂停 47 t.setDaemon(true); 48 t.start(); 49 50 Scanner sc=new Scanner(System.in); 51 sc.next(); 52 53 System.out.println("退出线程"+Thread.currentThread().getName()); 54 } 55 56 }
运行后的控制台显示:
进入线程main
进入守护线程Thread-0
守护线程Thread-0向文件中写入word0
守护线程Thread-0向文件中写入word1
守护线程Thread-0向文件中写入word2....
(一直走到999,知道你在控制台用键盘输入任意字符等,就会变成下面)
退出线程main
注意事项:
SetDaemon(true)必须是在start()方法之前调用,否则会抛出IllegalThreadStateException异常
在守护线程中产生的新线程也是守护线程
不是所有的任务都可以分配给守护线程来执行,比如读写操作或者计算逻辑
使用jstack生成线程快照?
命令行工具,界面化工具
作用:生成JVM当前时刻线程的快照
目的:帮助定位程序问题出现的原因,如长时间停顿、CUP占用率过高等
jstack如何使用这里就不详细说了。