java学习笔记——多线程基础

创建新线程

继承Thread类重写run方法

package example;

public class Work extends Thread {
    @Override
    public void run() {
        super.run();
        System.out.println("new thread start");
    }

}

  也可以直接写在创建处

package example;

public class Main {
    public static void main(String[] args) {
        Thread thread = new Thread(){
            @Override
            public void run() {
                super.run();
                System.out.println("new thread start");
            }
        };
        thread.start();
    }
}

  用Lambda表达式可以简写这一过程

package example;

public class Main {
    public static void main(String[] args) {
        Thread thread = new Thread(()->{
            System.out.println("new thread start");
        });
        thread.start();
    }
}

实现 Runnable 接口,重写 run 方法,作为参数传入Thread()

package example;

public class Work implements Runnable {
    @Override
    public void run() {
        System.out.println("new thread start");
    }
}

  或者直接在参数里创建

package example;

public class Main {
    public static void main(String[] args) {
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("new thread start");
            }
        });
        thread.start();
    }
}

Thread 构造方法参数

private Thread(ThreadGroup g, Runnable target, String name,
                   long stackSize, AccessControlContext acc,
                   boolean inheritThreadLocals)
  • ThreadGroup g:线程组
  • Runnable target:要执行的任务
  • String name:线程名

Thread 常用方法

currentThread()

  静态方法,返回对当前正在执行的线程对象的引用

start()

  在原线程执行,启动新线程,接着会在新线程内自动执行 run() 方法,一个线程只能执行一次 start() 方法

yield()

  指当前线程愿意让出对当前处理器的占用

sleep()

  静态方法,使当前线程挂起一段时间

join()

  使当前线程等待另一个线程执行完毕之后再继续执行

setPriority(int n)

  静态方法,设置线程的优先级,供操作系统调度使用

线程的状态

  • New:新创建的线程,尚未执行;
  • Runnable:运行中的线程,正在执行run()方法的Java代码;
  • Blocked:运行中的线程,因为某些操作被阻塞而挂起;
  • Waiting:运行中的线程,因为某些操作在等待中;
    • Object.wait():使当前线程处于等待状态直到另一个线程唤醒它;
    • Thread.join():等待线程执行完毕,底层调用的是Object实例的wait方法;
    • LockSupport.park():除非获得调用许可,否则禁用当前线程进行线程调度。
  • Timed Waiting:运行中的线程,因为执行sleep()方法正在计时等待;
    • Thread.sleep(long millis):使当前线程睡眠指定时间;
    • Object.wait(long timeout):线程休眠指定时间,等待期间可以通过notify()/notifyAll()唤醒;
    • Thread.join(long millis):等待当前线程最多执行millis毫秒,如果millis为0,则会一直执行;
    • LockSupport.parkNanos(long nanos): 除非获得调用许可,否则禁用当前线程进行线程调度指定时间;
    • LockSupport.parkUntil(long deadline):同上,也是禁止线程进行调度指定时间;
  • Terminated:线程已终止,因为run()方法执行完毕。

  可以使用 getState() 方法查看线程状态,这个方式只是给用户提供一个查看线程状态的方法,并不能用来进行线程同步控制

package example;

public class Main {
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("new thread start");
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        System.out.println(thread.getState());
        //NEW
        thread.start();
        System.out.println(thread.getState());
        //RUNNABLE
        Thread.sleep(1000);
        System.out.println(thread.getState());
        //TIMED_WAITING
        thread.join();
        System.out.println(thread.getState());
        //TERMINATED
    }
}

守护线程

  对于一般线程,如果线程没有结束,那么JVM就不会结束

  而对于守护线程,当所有非守护线程结束,就算守护线程没结束,JVM也会结束

  守护线程需要在线程启动前,由线程的引用调用 setDaemon(true) 来设置

package example;

public class Main {
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(()->{
            try {
                Thread.sleep(100000);
                System.out.println("after sleep");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        thread.setDaemon(true);
        thread.start();
    }
}

  运行程序会发现程序立即结束,没有打印任何信息,显然程序并没有等待守护线程结束

中断线程

使用 interrupt() 方法通知线程结束

  对于线程 t,其他线程如果调用 t.interrupt() 方法,在线程 t 内,isInterrupted() 就会返回true,通知线程结束操作

  如果线程处于等待,如在调用 join() 等待其他线程执行,join 会抛出 InterruptedException 异常,此时只要捕获到该异常,也就收到了结束线程的通知

使用共享变量通知

  在线程内,可以定义一个共享变量,供其他线程使用通知结束信号

public volatile boolean interupt = false;

  volatile 关键字告诉JVM要立刻更新内存中的信息

参考资料

多线程 - 廖雪峰的官方网站

深入浅出Java多线程

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章