首先咱们来看下代码:java
这是实现Runnable接口的方式数据库
class MyRunnable implements Runnable { private int ticketsCont = 5; @Override public void run() { while (ticketsCont > 0) { ticketsCont--; System.out.println(Thread.currentThread().getName() + "卖了1张票,剩余的票数为:" + ticketsCont); } } } public class TicketsRunnable { public static void main(String[] args) { MyRunnable myRunnable = new MyRunnable(); Thread thread1 = new Thread(myRunnable, "窗口1"); Thread thread2 = new Thread(myRunnable, "窗口2"); Thread thread3 = new Thread(myRunnable, "窗口3"); thread1.start(); thread2.start(); thread3.start(); } } //运行结果: //窗口1卖了1张票,剩余的票数为:4 //窗口1卖了1张票,剩余的票数为:3 //窗口1卖了1张票,剩余的票数为:2 //窗口1卖了1张票,剩余的票数为:1 //窗口1卖了1张票,剩余的票数为:0
这是继承Thread类的方式bash
class MyThread extends Thread { //火车票的总数 private int ticketsCont = 5; //线程的名字 private String name; public MyThread(String name) { this.name = name; } @Override public void run() { while (ticketsCont > 0) { ticketsCont--; System.out.println(name + "卖了一张票,剩余的票数为:" + ticketsCont); } } } public class TicketsThread { public static void main(String[] args) { MyThread t1 = new MyThread("窗口1"); MyThread t2 = new MyThread("窗口2"); MyThread t3 = new MyThread("窗口3"); t1.start(); t2.start(); t3.start(); } } //运行结果: //窗口1卖了一张票,剩余的票数为:4 //窗口1卖了一张票,剩余的票数为:3 //窗口1卖了一张票,剩余的票数为:2 //窗口1卖了一张票,剩余的票数为:1 //窗口1卖了一张票,剩余的票数为:0 //窗口3卖了一张票,剩余的票数为:4 //窗口3卖了一张票,剩余的票数为:3 //窗口3卖了一张票,剩余的票数为:2 //窗口3卖了一张票,剩余的票数为:1 //窗口3卖了一张票,剩余的票数为:0 //窗口2卖了一张票,剩余的票数为:4 //窗口2卖了一张票,剩余的票数为:3 //窗口2卖了一张票,剩余的票数为:2 //窗口2卖了一张票,剩余的票数为:1 //窗口2卖了一张票,剩余的票数为:0
运行得出结果,你就会发现两种方式的不一样:服务器
出现这种状况的缘由是两种不一样的线程实现方式自己就决定了其是否能进行资源共享:网络
Thread:app
一个线程只能启动一次,经过Thread实现线程时,线程和线程所要执行的任务是捆绑在一块儿的。
也就使得一个任务只能启动一个线程,不一样的线程执行的任务是不相同的,因此两个线程之间是不能共享资源的,也不必。
固然若是必定要Thread的实现资源共享,那么能够在共享变量加上static关键字。
Runnable:jvm
一个任务能够启动多个线程,经过Runnable方式实现的线程,实际是开辟一个线程,将任务传
递进去,由此线程执行。能够实例化多个 Thread对象,将同一任务传递进去,也就是一个任务能够
启动多个线程来执行它。这些线程执行的是同一个任务,因此他们的资源是共享。
因此说Runnable适合多个线程处理同一个资源的状况。socket
服务,具有了运行的条件,可是并不必定已经开始运行了)。ide
Java线程有两类this
守护线程: 运行在后台,为其余的前台线程服务
直接上代码:
class DaemonRunnable implements Runnable { private int count; @Override public void run() { System.out.println("进入守护线程" + Thread.currentThread().getName()); try { writeToFile(); } catch (Exception e) { e.printStackTrace(); } System.out.println("退出守护线程" + Thread.currentThread().getName()); } private void writeToFile() throws Exception { File filename=new File("E:"+File.separator+"Daemon.txt"); OutputStream os = new FileOutputStream(String.valueOf(filename), true); int count = 0; while (count < 999) { os.write(("\r\n world" + count).getBytes()); System.out.println("守护线程" + Thread.currentThread().getName() + "向文件中写入了world" + count++); Thread.sleep(1000); } } } public class DaemonDemo { public static void main(String []args){ System.out.println("进入主线程"+Thread.currentThread().getName()); DaemonRunnable daemonRunnable=new DaemonRunnable(); Thread thread= new Thread(daemonRunnable); thread.setDaemon(true);//设置为守护线程 thread.start(); Scanner scanner=new Scanner(System.in); scanner.next(); System.out.println("退出主线程"+Thread.currentThread().getName()); } }
这时候经过的在Console中随便输入字符让主线程中止。
进入主线程main 进入守护线程Thread-0 守护线程Thread-0向文件中写入了world0 守护线程Thread-0向文件中写入了world1 守护线程Thread-0向文件中写入了world2 守护线程Thread-0向文件中写入了world3 11 退出主线程main
能够看到用户线程中止的时候,守护线程也中止了。
setDaemon(true)
必须在start()方法以前调用,不然会抛出IllegalThreadStateException
异常jstack是一个.exe的命令行程序,在jdk安装目录的bin目录下。
个人jdk是默认安装在C盘的,因此路径是:C:\Program Files\Java\jdk1.8.0_131\bin
。
在bin目录下打开Terminal,输入jstack。
C:\Program Files\Java\jdk1.8.0_131\bin>jstack Usage: jstack [-l] <pid> (to connect to running process) jstack -F [-m] [-l] <pid> (to connect to a hung process) jstack [-m] [-l] <executable> <core> (to connect to a core file) jstack [-m] [-l] [server_id@]<remote server IP or hostname> (to connect to a remote debug server) Options: -F to force a thread dump. Use when jstack <pid> does not respond (process is hung) -m to print both java and native frames (mixed mode) -l long listing. Prints additional information about locks -h or -help to print this help message
能够看到jstack是经过pid码来获取线程快照信息的。
咱们能够打开任务管理器的 -> 详细服务,就能够看到当前正在运行的程序的pid码。
而后咱们启动主线程开始运行,在Terminal中输入:jstack -l 4528
。
4528是我当前运行的程序的pid码,若是没有相应的pid码,那么会提示拒绝访问。
C:\Program Files\Java\jdk1.8.0_131\bin>jstack -l 804 2017-06-24 11:01:25 // 使用的Java虚拟机版本为Oracle的HotSpot 64位服务器版本 Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.131-b11 mixed mode): "Thread-0" #11 daemon prio=5 os_prio=0 tid=0x00000000188ca800 nid=0x2560 waiting on condition [0x000000001941f000] java.lang.Thread.State: TIMED_WAITING (sleeping) at java.lang.Thread.sleep(Native Method) at Thread.demo.DaemonRunnable.writeToFile(DaemonDemo.java:32) at Thread.demo.DaemonRunnable.run(DaemonDemo.java:18) at java.lang.Thread.run(Thread.java:748) Locked ownable synchronizers: - None "Service Thread" #10 daemon prio=9 os_prio=0 tid=0x00000000187fc800 nid=0x252c runnable [0x0000000000000000] java.lang.Thread.State: RUNNABLE Locked ownable synchronizers: - None "C1 CompilerThread2" #9 daemon prio=9 os_prio=2 tid=0x00000000187cf000 nid=0x2038 waiting on condition [0x0000000000000000] java.lang.Thread.State: RUNNABLE Locked ownable synchronizers: - None "C2 CompilerThread1" #8 daemon prio=9 os_prio=2 tid=0x0000000018774800 nid=0x20c8 waiting on condition [0x0000000000000000] java.lang.Thread.State: RUNNABLE Locked ownable synchronizers: - None "C2 CompilerThread0" #7 daemon prio=9 os_prio=2 tid=0x0000000018771800 nid=0x2298 waiting on condition [0x0000000000000000] java.lang.Thread.State: RUNNABLE Locked ownable synchronizers: - None "Monitor Ctrl-Break" #6 daemon prio=5 os_prio=0 tid=0x000000001876f800 nid=0x16e0 runnable [0x0000000018e1e000] java.lang.Thread.State: RUNNABLE at java.net.SocketInputStream.socketRead0(Native Method) at java.net.SocketInputStream.socketRead(SocketInputStream.java:116) at java.net.SocketInputStream.read(SocketInputStream.java:171) at java.net.SocketInputStream.read(SocketInputStream.java:141) at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284) at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326) at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178) - locked <0x00000000d6132b90> (a java.io.InputStreamReader) at java.io.InputStreamReader.read(InputStreamReader.java:184) at java.io.BufferedReader.fill(BufferedReader.java:161) at java.io.BufferedReader.readLine(BufferedReader.java:324) - locked <0x00000000d6132b90> (a java.io.InputStreamReader) at java.io.BufferedReader.readLine(BufferedReader.java:389) at com.intellij.rt.execution.application.AppMainV2$1.run(AppMainV2.java:64) Locked ownable synchronizers: - None "Attach Listener" #5 daemon prio=5 os_prio=2 tid=0x0000000017418000 nid=0x1404 waiting on condition [0x0000000000000000] java.lang.Thread.State: RUNNABLE Locked ownable synchronizers: - None "Signal Dispatcher" #4 daemon prio=9 os_prio=2 tid=0x00000000173ce800 nid=0x1b20 runnable [0x0000000000000000] java.lang.Thread.State: RUNNABLE Locked ownable synchronizers: - None "Finalizer" #3 daemon prio=8 os_prio=1 tid=0x000000000288d800 nid=0xf64 in Object.wait() [0x000000001871f000] java.lang.Thread.State: WAITING (on object monitor) at java.lang.Object.wait(Native Method) - waiting on <0x00000000d5f08ec8> (a java.lang.ref.ReferenceQueue$Lock) at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:143) - locked <0x00000000d5f08ec8> (a java.lang.ref.ReferenceQueue$Lock) at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:164) at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:209) Locked ownable synchronizers: - None "Reference Handler" #2 daemon prio=10 os_prio=2 tid=0x0000000002882000 nid=0x148c in Object.wait() [0x000000001861f000] java.lang.Thread.State: WAITING (on object monitor) at java.lang.Object.wait(Native Method) - waiting on <0x00000000d5f06b68> (a java.lang.ref.Reference$Lock) at java.lang.Object.wait(Object.java:502) at java.lang.ref.Reference.tryHandlePending(Reference.java:191) - locked <0x00000000d5f06b68> (a java.lang.ref.Reference$Lock) at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153) Locked ownable synchronizers: - None "main" #1 prio=5 os_prio=0 tid=0x000000000085e800 nid=0x27d4 runnable [0x000000000215e000] java.lang.Thread.State: RUNNABLE at java.io.FileInputStream.readBytes(Native Method) at java.io.FileInputStream.read(FileInputStream.java:255) at java.io.BufferedInputStream.read1(BufferedInputStream.java:284) at java.io.BufferedInputStream.read(BufferedInputStream.java:345) - locked <0x00000000d5f5a498> (a java.io.BufferedInputStream) at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284) at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326) at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178) - locked <0x00000000d60ada70> (a java.io.InputStreamReader) at java.io.InputStreamReader.read(InputStreamReader.java:184) at java.io.Reader.read(Reader.java:100) at java.util.Scanner.readInput(Scanner.java:804) at java.util.Scanner.next(Scanner.java:1369) at Thread.demo.DaemonDemo.main(DaemonDemo.java:45) Locked ownable synchronizers: - None "VM Thread" os_prio=2 tid=0x0000000017386800 nid=0x1f68 runnable "GC task thread#0 (ParallelGC)" os_prio=0 tid=0x00000000027a7800 nid=0x2a24 runnable "GC task thread#1 (ParallelGC)" os_prio=0 tid=0x00000000027a9000 nid=0x71c runnable "GC task thread#2 (ParallelGC)" os_prio=0 tid=0x00000000027aa800 nid=0x16bc runnable "GC task thread#3 (ParallelGC)" os_prio=0 tid=0x00000000027ac000 nid=0x1d24 runnable "VM Periodic Task Thread" os_prio=2 tid=0x000000001882e000 nid=0x1e30 waiting on condition JNI global references: 33
我就拿Thread-0这个线程的信息作解释:
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.131-b11 mixed mode)
表示使用的是Oracle HotSpot64版本的JVM,为服务器版本,客户端版本为Client
"Thread-0" #11 daemon prio=5 os_prio=0 tid=0x00000000188ca800 nid=0x2560 waiting on condition [0x000000001941f000] java.lang.Thread.State: TIMED_WAITING (sleeping) at java.lang.Thread.sleep(Native Method) at Thread.demo.DaemonRunnable.writeToFile(DaemonDemo.java:32) at Thread.demo.DaemonRunnable.run(DaemonDemo.java:18) at java.lang.Thread.run(Thread.java:748) Locked ownable synchronizers: - None
Thread-0
表示这个线程的名字daemon
表示该线程为守护线程prio=5
表示线程的优先级tid
和nid
也是线程的16进制信息,结合其余指令能够很方便的定位出cpu占有率很高的线程java.lang.Thread.State: TIMED_WAITING (sleeping)
表示线程的状态为TIMED_WAITING,这是调用了sleep()方法产生的结果-l
参数的话,Locked ownable synchronizers:- None
这一段信息是不会显示出来的,这段表示的是锁的额外信息,None表示为没有。
至于其余的线程信息的话,有兴趣的人能够去查阅相关的资料,在这里就不去作更多的介绍。