细说多线程之Thread VS Runnable

来源:互联网 发布:淘宝网波司登羽绒服 编辑:程序博客网 时间:2024/05/20 17:10

1.继承Thread类

package com.yd.test.testthread;

public class MyThread extends Thread {
    @Override
    public void run() {
        // TODO Auto-generated method stub
        System.out.println("nihao");
        super.run();
    }

    public static void main(String[] args) {

        MyThread mt = new MyThread();//创建线程
        mt.start();//启动线程,当线程启动的时候,这个时候线程进入到线程队列中,这个时候等待cpu的服务,一旦它获取了CPU的时间片,这个时候它就会转到run方法中去执行,当run()中的逻辑执行完以后,这个线程
        //也就消亡了.
    }

}

2.实现Runnable接口

package com.yd.test.testthread;

public class MyThread1 implements Runnable {

    public static void main(String[] args) {
        MyThread1 mt1 = new MyThread1();
        Thread td = new Thread(mt1);//创建线程,只不过 传入了一个线程类的对象
        td.start();//启动线程,当start()的时候,同样线程会加入到线程队列中,一旦获取CPU的时间片之后就会转到run()中执行,当run()中的逻辑执行完以后,线程也就消亡了
    }

    @Override
    public void run() {
        // TODO Auto-generated method stub
        System.out.println("nihao1");
    }
    
    /**
     * 无论哪种方法都需要创建线程类的对象,启动线程都需要调用start();
     * Runabble方式可以避免extends Thread单继承带来的缺陷
     * Runbale的代码可以实现多个线程实例的共享,适合多个线程处理同一资源的情况.
     */

}

3.火车票卖票案例

3.1 Thread类方式

package com.yd.test.testthread.ticketsThread;

/**
 * 线程的生命周期:
 * 创建状态(new Thread时候),
 * 就绪状态(start被调用后,加入到线程队列),
 * 运行状态(获取CPU时间片的时候),
 * 阻塞状态(由于某种原因,让出的CPU资源,比如sleep时候),
 * 终止状态(run执行完毕,人为终止)
 * @author think
 *用户线程:运行在前台,执行具体的任务:程序的主线程,连接网络的子线程等都是用户线程.
 *守护线程:运行在后台,为其他前台线程提供服务.
 *特点:一旦所有用户线程都结束运行,守护线程会随jvm一起结束工作
 *应用:数据库连接池的监测线程,jvm启动后的监测线程
 *最常见的守护线程:垃圾回收线程
 *设置:Thread.setDaemon(true)来设置当前线程为守护线程,必须在start()方法之前调用,否则会抛出IllegalThreadStateException.
 *在守护线程中产生的新线程也是守护线程,并不是所有的任务都可以分配给守护线程来执行的,比如读写操作或者计算逻辑
 */
class MyThread extends Thread {
    private int ticketsCount = 5;// 一共有5张火车票
    private String name;// 窗口,就是线程的名字

    public MyThread(String name) {
        this.name = name;
    }

    @Override
    public void run() {
        // TODO Auto-generated method stub
        super.run();
        while (ticketsCount > 0) {
            ticketsCount--;// 如果还有票就卖掉一张
            System.out.println(name + "窗口卖了1张票,剩余票数为:" + ticketsCount);

        }
    }
}

public class TicketsThread {
    public static void main(String[] args) {
        //new了三个独立的Thread对象,他们是独立的,不是共享的,所以是卖了15张票.
        // 创建3个线程,模拟三个窗口买票
        MyThread t1 = new MyThread("窗口1");
        MyThread t2 = new MyThread("窗口2");
        MyThread t3 = new MyThread("窗口3");

        // 启动这三个线程,也就是三个窗口
        t1.start();
        t2.start();
        t3.start();

    }
}

3.2 Runnable方式

package com.yd.test.testthread.ticketsRunnable;

class MyThread implements Runnable {

    private int ticketsCount = 5;// 一共有5张票

    @Override
    public void run() {
        while (ticketsCount > 0) {
            ticketsCount--;// 如果还有票就卖掉一张
            System.out.println(Thread.currentThread().getName() + "卖掉了1张票,还剩下" + ticketsCount);
        }
    }

}

public class TicketsRunnable {
    public static void main(String[] args) {
        MyThread mt = new MyThread();//三个线程传递的是同一个runnable对象,用的也是runnable对象的同一个代码,相应的对应的资源(ticketsCount=5)也是共享的
        Thread t1 = new Thread(mt, "窗口1");
        Thread t2 = new Thread(mt, "窗口2");
        Thread t3 = new Thread(mt, "窗口3");

        t1.start();
        t2.start();
        t3.start();
    }
}

/**
 *  窗口2卖掉了1张票,还剩下3
    窗口3卖掉了1张票,还剩下2
    窗口1卖掉了1张票,还剩下3
    窗口3卖掉了1张票,还剩下0
    窗口2卖掉了1张票,还剩下1
    */

4.守护线程案例

package com.yd.test.testthread.daemon;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Scanner;

/**
 * 场景:一个主线程,一个守护线程: 守护线程是在某一个时间内不停的向文件中写数据,
 * 主线程会阻塞等待来自键盘的输入,一旦主线程获取到用户的输入,这个时候主线程就会解除阻塞,主线程继续运行直到结束,一旦主线程执行结束,用户线程就没有了.
 * 这个时候即使守护线程没有写完,守护线程也会随虚拟机一起消亡
 *
 * @author think
 *
 */

class DaemonThread implements Runnable {

    @Override
    public void run() {
        // TODO Auto-generated method stub
        System.out.println("进入守护线程" + Thread.currentThread().getName());
        try {
            writeToFile();
        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("退出守护线程" + Thread.currentThread().getName());
    }

    private void writeToFile() throws IOException, InterruptedException {
        // TODO Auto-generated method stub
        File fileName = new File("d:" + File.separator + "daemon.txt");
        OutputStream os = new FileOutputStream(fileName, true);// true,说明每次都是追加操作,而不是覆盖操作
        int count = 0;
        while (count < 999) {
            os.write(("\r\nword" + count).getBytes());
            System.out.println("守护线程" + Thread.currentThread().getName() + "向文件中写入了word" + count++);
            Thread.sleep(1000);
        }
    }

}

public class DaemonThreadDemo {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        System.out.println("进入主线程" + Thread.currentThread().getName());
        DaemonThread damonThread = new DaemonThread();
        Thread t = new Thread(damonThread);
        t.setDaemon(true);
        t.start();
        Scanner sc = new Scanner(System.in);//参数是System.in表示从键盘接收输入
        sc.next();//这个时候主线程就阻塞住了,一旦执行了输入操作,这个时候,阻塞就会解除掉,主线程就会继续往下执行,从而打印"退出运行".
        //由于主线程是唯一的用户线程,一旦主线程退出运行,守护线程就会退出运行.就会导致守护线程输入数据的不完整性
        System.out.println("退出主线程" + Thread.currentThread().getName());
    }

    /**
     * C:\Program Files\Java\jdk1.7.0_07\bin
     * jmap.exe:用来生成堆快照的
     * jstat.exe:监测虚拟机的运行状态的,查看jvm中内存使用的情况,类加载的情况,或者是所持有的情况等等.(生成jvm当前时刻线程的快照<Threaddump>即当前线程中所有线程的信息;目的:帮助定位
     * 程序问题出现的原因,如长时间停顿,CPU占用率过高等)
     * C:\Users\think>jstack
Usage:
    jstack [-l] <pid>pid:进程的id,有了这个参数就会打印出当前进程中所有线程的信息
        (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
     * jconsole.exe和jstat的功能一样,是界面化工具.
     *
     *
     *
     *
     * C:\Users\think>jstack -l 10060
2017-12-26 13:44:26 快照的生成时间
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.131-b11 mixed mode): 使用的jvm类型,服务器端版本
 
 以下是所有的线程信息的快照:每一部分都对应一个线程的信息
 proio:优先级 tid nid:16进制,通过top工具,定位CPU占有率
"Thread-0" #10 daemon prio=5 os_prio=0 tid=0x00000000189c7000 nid=0xca0 waiting on condition [0x00000000194ef000]
   java.lang.Thread.State: TIMED_WAITING (sleeping)
        at java.lang.Thread.sleep(Native Method)
        at com.yd.test.testthread.daemon.DaemonThread.writeToFile(DaemonThreadDemo.java:41)
        at com.yd.test.testthread.daemon.DaemonThread.run(DaemonThreadDemo.java:26)
        at java.lang.Thread.run(Thread.java:748)

   Locked ownable synchronizers:当前线程是否处于同步块内
        - None:没有
以下:是jvm启动的时候,自己启动起来的,无论运行那个程序都会起来
"Service Thread" #9 daemon prio=9 os_prio=0 tid=0x0000000018987800 nid=0x2728 runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
        - None

//用来调用jit编译器的
"C1 CompilerThread2" #8 daemon prio=9 os_prio=2 tid=0x0000000018902000 nid=0x3340 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
        - None

"C2 CompilerThread1" #7 daemon prio=9 os_prio=2 tid=0x00000000188ff000 nid=0x3e98 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
        - None

"C2 CompilerThread0" #6 daemon prio=9 os_prio=2 tid=0x00000000188f9800 nid=0x3c94 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
        - None

"Attach Listener" #5 daemon prio=5 os_prio=2 tid=0x0000000017421000 nid=0x2624 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
        - None

"Signal Dispatcher" #4 daemon prio=9 os_prio=2 tid=0x00000000188f8800 nid=0x2eb0 runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
        - None

"Finalizer" #3 daemon prio=8 os_prio=1 tid=0x000000000290d800 nid=0x1a20 in Object.wait() [0x000000001877e000]
   java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0x00000000d6188ec8> (a java.lang.ref.ReferenceQueue$Lock)
        at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:143)
        - locked <0x00000000d6188ec8> (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=0x0000000002902800 nid=0x3ce0 in Object.wait() [0x000000001867e000]
   java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0x00000000d6186b68> (a java.lang.ref.Reference$Lock)
        at java.lang.Object.wait(Object.java:502)
        at java.lang.ref.Reference.tryHandlePending(Reference.java:191)
        - locked <0x00000000d6186b68> (a java.lang.ref.Reference$Lock)
        at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153)

   Locked ownable synchronizers:
        - None

主线程,没有daemon标记,说明是用户线程
"main" #1 prio=5 os_prio=0 tid=0x0000000002813800 nid=0x1f38 runnable [0x00000000027ff000]
   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 <0x00000000d61dde10> (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 <0x00000000d6267d78> (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 com.yd.test.testthread.daemon.DaemonThreadDemo.main(DaemonThreadDemo.java:57)

   Locked ownable synchronizers:
        - None

"VM Thread" os_prio=2 tid=0x00000000173d7800 nid=0x488 runnable

"GC task thread#0 (ParallelGC)" os_prio=0 tid=0x0000000002829800 nid=0xcc4 runnable

"GC task thread#1 (ParallelGC)" os_prio=0 tid=0x000000000282b000 nid=0x13ec runnable

"GC task thread#2 (ParallelGC)" os_prio=0 tid=0x000000000282d000 nid=0x4270 runnable

"GC task thread#3 (ParallelGC)" os_prio=0 tid=0x000000000282e800 nid=0x15d8 runnable

"VM Periodic Task Thread" os_prio=2 tid=0x00000000189b5000 nid=0x3f04 waiting on condition

JNI global references: 6
     *
     *
     *
     *
     *
     */
}


阅读全文
'); })();
0 0
原创粉丝点击
热门IT博客
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 失落的句子 斩龙失落叶 失落的龙约 斗神失落叶 失落之城 失落世界 失落的世界 失落城 失落的方舟 失落的 寻找失落的爱情六宫凤华 心情失落句子 路灯下男生失落背影图片 男生失落背影图片 失落一个人喝酒图片 失落叶网游三部曲 纵横天下失落叶 失落的大陆免费观看 网游纵横天下失落叶 网游之纵横天下失落叶 希望你到夜里就失落 失衡 失衡的美丽 心理失衡 失衡by白芥子 微生态失衡是什么意思 透析失衡综合征 水油失衡长痘怎么调理 国际收支失衡的原因 混元无极功 失衡的天平 体内激素分泌失衡怎么办 00后性别比例失衡加剧 位面拯救系统 维度失衡 天龙之王语嫣失处记 失语症 运动性失语 失语 感觉性失语 言多语失 失语症6种类型 命名性失语