Java进阶:线程

线程

  • 进程与线程概述
  • 实现线程的两种方式
    • 第一种方式:编写一个类,直接继承java.lang.Thread,重写run方法。
    • 第二种方式:编写一个类,实现java.lang.Runnable接口,实现run方法。
  • 线程对象的生命周期
  • 线程常用方法
  • 线程的sleep方法
  • 终断线程的睡眠
  • 强行终止线程的执行(不建议使用)
  • 合理终止当前线程的执行
  • 线程的优先级(了解)
  • 线程让位
  • 线程合并

进程与线程概述

进程是一个应用程序。
线程是一个进程中的执行场景/执行单元。
一个进程可以启动多个线程。

实现线程的两种方式

第一种方式:编写一个类,直接继承java.lang.Thread,重写run方法。

/*
实现线程的第一种方式:
    编写一个类,直接继承java.lang.Thread,重写run方法。
 */
public class ThreadTest {
    public static void main(String[] args) {
        // 主线程
        // 新建一个分支线程对象
        MyThread myThread = new MyThread();
        // 启动线程
        //myThread.run(); // 不会启动线程,不会分配新的分支栈(单线程)
        // start()方法的作用:启动一个分支线程,在JVM中开辟一个新的栈空间。
        myThread.start(); // 启动后就结束了
        for (int i = 0; i < 100; i++) {
            System.out.println("主线程-->" + i);
        }
    }
}

// 定义线程类
class MyThread extends Thread {
    @Override
    public void run(){
        for (int i = 0; i < 100; i++) {
            System.out.println("分支线程-->" + i);
        }
    }
}

第二种方式:编写一个类,实现java.lang.Runnable接口,实现run方法。

/*
实现线程的第二种方式:
    编写一个类,实现java.lang.Runnable接口,实现run方法。
 */
public class ThreadTest01 {
    public static void main(String[] args) {
        // 创建一个可运行的对象
        MyRunnable myRunnable = new MyRunnable();
        // 将可运行的对象封装成一个线程对象
        Thread thread = new Thread(myRunnable);
        // 启动线程
        thread.start();

        for (int i = 0; i < 100; i++) {
            System.out.println("主线程-->" + i);
        }
    }
}

// 这个不是线程类,是一个可运行的类
class MyRunnable implements Runnable {
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println("分支线程-->" + i);
        }
    }
}

采用匿名内部类方式实现

public class ThreadTest02 {
    public static void main(String[] args) {
        // 采用匿名内部类方式创建线程对象
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 100; i++) {
                    System.out.println("分支线程-->" + i);
                }
            }
        });
        // 启动线程
        thread.start();

        for (int i = 0; i < 100; i++) {
            System.out.println("主线程-->" + i);
        }
    }
}

注意:第二种方式实现接口比较常用,因为一个类实现了接口,它还可以去继承其它的类,更灵活。

线程对象的生命周期

新建状态、就绪状态、运行状态、阻塞状态、死亡状态
Java进阶:线程_第1张图片

线程常用方法

  1. Thread.currentThread() 获取当前线程对象
  2. 线程对象.getName() 获取线程对象的名字
    名字规律:Thread-0、Thread-1、Thread-2、…
  3. 线程对象.setName() 修改线程对象的名字
public class ThreadTest03 {
    public static void main(String[] args) {

        // Thread.currentThread() 获取当前线程对象
        // 这个代码出现在main方法中,所以当前线程就是主线程
        Thread thread = Thread.currentThread();
        System.out.println(thread.getName());   //main

        // 新建一个分支线程对象
        MyThreads myThread = new MyThreads();

        // 获取线程的名字
        System.out.println(myThread.getName()); //Thread-0
        // 设置线程的名字
        myThread.setName("myThread");
        // 获取线程的名字
        System.out.println(myThread.getName()); //myThread

        // 新建一个分支线程对象
        MyThreads myThread1 = new MyThreads();
        // 获取线程的名字
        System.out.println(myThread1.getName()); //Thread-1

        // 启动线程
        myThread.start();
        myThread1.start();
    }
}

// 定义线程类
class MyThreads extends Thread {
    @Override
    public void run(){
        for (int i = 0; i < 100; i++) {
            Thread thread = Thread.currentThread();
            System.out.println(thread.getName() + "-->" + i);
        }
    }
}

线程的sleep方法

/*
关于线程的sleep方法:
    static void sleep(long millis)
    1. 静态方法
    2. Thread.sleep(休眠时间【毫秒】);
    3. 作用:让当前线程进入休眠,进入”阻塞状态“,放弃占有的CPU时间片。
 */
public class ThreadTest04 {
    public static void main(String[] args) {
        try {
            // 让当前线程休眠3秒
            Thread.sleep(1000*3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // 这里的代码3秒之后执行
        System.out.println("hello world!");

        for (int i = 0; i < 10; i++) {
            System.out.println(Thread.currentThread().getName() + "-->" + i);
            try {
                // 让当前线程每隔1秒执行
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

终断线程的睡眠

public class ThreadTest05 {
    public static void main(String[] args) {
        Thread thread = new Thread(new MyRunnable1());
        thread.setName("t");
        thread.start();
        // 希望5秒后,t线程醒来
        try {
            Thread.sleep(1000*5);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // 终断t线程的睡眠(依靠java的异常处理机制)
        thread.interrupt();
    }
}

class MyRunnable1 implements Runnable {
    @Override
    public void run(){
        System.out.println(Thread.currentThread().getName() + "--> begin");
        try {
            // 睡眠1年
            Thread.sleep(1000*60*60*24*365);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // 1年后执行
        System.out.println(Thread.currentThread().getName() + "--> end");
    }
}

强行终止线程的执行(不建议使用)

public class ThreadTest06 {
    public static void main(String[] args) {
        Thread thread = new Thread(new MyRunnable2());
        thread.setName("t");
        thread.start();

        try {
            // 睡眠5秒
            Thread.sleep(1000*5);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        // 强行终止t线程
        // stop() 缺点:容易丢失数据
        thread.stop();  //已过时,不建议使用
    }
}

class MyRunnable2 implements Runnable {
    @Override
    public void run(){
        for (int i = 0; i < 10; i++) {
            System.out.println(Thread.currentThread().getName() + "-->" +i);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

合理终止当前线程的执行

public class ThreadTest07 {
    public static void main(String[] args) {
        MyRunnable3 myRunnable = new MyRunnable3();
        Thread thread = new Thread(myRunnable);
        thread.setName("t");
        thread.start();

        try {
            // 睡眠5秒
            Thread.sleep(1000*5);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        // 终止线程
        myRunnable.run = false;
    }
}

class MyRunnable3 implements Runnable {
    boolean run = true;
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            if (run) {
                System.out.println(Thread.currentThread().getName() + "-->" + i);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            } else {
                // 终止当前线程
                return;
            }
        }
    }
}

线程的优先级(了解)

public class ThreadTest08 {
    public static void main(String[] args) {
        System.out.println("最高优先级" + Thread.MAX_PRIORITY);  //最高优先级10
        System.out.println("最低优先级" + Thread.MIN_PRIORITY);  //最低优先级1
        System.out.println("默认优先级" + Thread.NORM_PRIORITY); //默认优先级5

        // 设置主线程的优先级为1
        Thread.currentThread().setPriority(1);

        // 获取当前线程对象,以及当前线程的优先级
        Thread thread = Thread.currentThread();
        // main线程的默认优先级是:5
        System.out.println(thread.getName() + "线程的默认优先级是:" + thread.getPriority());

        Thread t = new Thread(new MyRunnable4());
        // 设置t线程的优先级为10
        t.setPriority(10);
        t.setName("t");
        t.start();

        // 优先级高的,只是抢到的CPU时间片会相对多一些
        for (int i = 0; i < 100; i++) {
            System.out.println(Thread.currentThread().getName() + "-->" + i);
        }
    }
}
class MyRunnable4 implements Runnable {
    @Override
    public void run() {
        // t线程的默认优先级是:5
        //System.out.println(Thread.currentThread().getName() + "线程的默认优先级是:" + Thread.currentThread().getPriority());
        for (int i = 0; i < 100; i++) {
            System.out.println(Thread.currentThread().getName() + "-->" + i);
        }
    }
}

线程让位

让位,当前线程暂停,回到就绪状态,让给其它线程。
静态方法:Thread.yield();

public class ThreadTest09 {
    public static void main(String[] args) {
        Thread thread = new Thread(new MyRunnable5());
        thread.setName("t");
        thread.start();
        for (int i = 1; i <= 100; i++) {
            System.out.println(Thread.currentThread().getName() + "-->" + i);
        }
    }
}

class MyRunnable5 implements Runnable {
    @Override
    public void run() {
        for (int i = 1; i <= 100; i++) {
            // 每10个让位一次
            if (i % 10 == 0) {
                Thread.yield(); //当前线程暂停一下让给主线程
            }
            System.out.println(Thread.currentThread().getName() + "-->" + i);
        }
    }
}

线程合并

public class ThreadTest10 {
    public static void main(String[] args) {
        System.out.println("main begin");

        Thread thread = new Thread(new MyRunnable6());
        thread.setName("t");
        thread.start();

        // 合并线程
        try {
            thread.join();  // t合并到当前线程中,当前线程受阻塞,t线程执行直到结束。
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("main over");
    }
}

class MyRunnable6 implements Runnable {
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println(Thread.currentThread().getName() + "-->" + i);
        }
    }
}

运行结果:

main begin
t-->0
t-->1
t-->2
t-->3
t-->4
t-->5
t-->6
t-->7
t-->8
t-->9
main over

你可能感兴趣的:(Java,java)