Java并发与多线程(一)--线程基础知识

一:简述

由于有的读者反馈我多线程的专栏应该从基础基础讲起,所以本篇文章就补上多线程相关的基础知识,当做Java并发与多线程专栏的第一篇文章,主要介绍java多线程的一些基础知识

二:java的线程状态

public enum State {
        /**
         * Thread state for a thread which has not yet started.
         */ 
        NEW,

        /**
         * Thread state for a runnable thread.  A thread in the runnable
         * state is executing in the Java virtual machine but it may
         * be waiting for other resources from the operating system
         * such as processor.
         */
        RUNNABLE,

        /**
         * Thread state for a thread blocked waiting for a monitor lock.
         * A thread in the blocked state is waiting for a monitor lock
         * to enter a synchronized block/method or
         * reenter a synchronized block/method after calling
         * {@link Object#wait() Object.wait}.
         */
        BLOCKED,

        /**
         * Thread state for a waiting thread.
         * A thread is in the waiting state due to calling one of the
         * following methods:
         * <ul>
         *   <li>{@link Object#wait() Object.wait} with no timeout</li>
         *   <li>{@link #join() Thread.join} with no timeout</li>
         *   <li>{@link LockSupport#park() LockSupport.park}</li>
         * </ul>
         *
         * <p>A thread in the waiting state is waiting for another thread to
         * perform a particular action.
         *
         * For example, a thread that has called <tt>Object.wait()</tt>
         * on an object is waiting for another thread to call
         * <tt>Object.notify()</tt> or <tt>Object.notifyAll()</tt> on
         * that object. A thread that has called <tt>Thread.join()</tt>
         * is waiting for a specified thread to terminate.
         */
        WAITING,

        /**
         * Thread state for a waiting thread with a specified waiting time.
         * A thread is in the timed waiting state due to calling one of
         * the following methods with a specified positive waiting time:
         * <ul>
         *   <li>{@link #sleep Thread.sleep}</li>
         *   <li>{@link Object#wait(long) Object.wait} with timeout</li>
         *   <li>{@link #join(long) Thread.join} with timeout</li>
         *   <li>{@link LockSupport#parkNanos LockSupport.parkNanos}</li>
         *   <li>{@link LockSupport#parkUntil LockSupport.parkUntil}</li>
         * </ul>
         */
        TIMED_WAITING,

        /**
         * Thread state for a terminated thread.
         * The thread has completed execution.
         */
        TERMINATED;
    }
复制代码

java线程有六种状态

1.NEW: 新生状态,线程创建了,但是没有调用start()方法,就处于这种状态

2.RUNNABLE: 可运行状态 线程调用start()方法进入该状态 该状态下可以被cpu调度

3.BLOCKED 阻塞状态,线程被synchronized锁阻塞进入该状态

4.WAITING 等待状态,线程调用wait(),join(),LockSupport.park()方法会进入该状态

5.TIMED_WAITING 有时间限制的等待状态,线程调用了 wait(timeout),sleep(timeout), join(timeout),LockSupport.parkNanos(timeout),LockSupport.parkUntil()等方法会进入该状态

6.TERMINATED 结束状态,调用stop(),destroy()等方法(因为不安全,在java8中已经删除)或者线程run()方法执行完成会进入该状态。

java线程的状态转化.png

三: 线程的创建

1.实现Runnable 实现run()方法

public class TestThread implements Runnable {
    @Override
    public void run() {
        System.out.println("java多线程");
    }

    public static void main(String[] args) {
        Thread thread = new Thread(new TestThread());
        thread.start();
    }
}
复制代码

2.继承Thread类 重写run()方法

public class TestThread extends Thread {
    @Override
    public void run() {
        System.out.println("java多线程");
    }

    public static void main(String[] args) {
        TestThread thread = new TestThread();
        thread.start();
    }
}
复制代码

3.实现Callable,实现call()方法

public class TestThread implements Callable {

    @Override
    public Object call() throws Exception {
        System.out.println("java多线程");
        return null;
    }

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        FutureTask futureTask = new FutureTask<>(new TestThread());
        futureTask.run();
        //阻塞获取线程的执行结果
        Object o = futureTask.get();
    }
}
复制代码

四:线程的停止和中断

线程的停止

线程停止的方法有两种

方法一:调用stop(),destroy()等方法,直接强制停止线程,这种方式存在严重的安全问题,所以不推荐使用 并且在java8中已经被删除。

方法二:run()方法执行完成

public class TestThread implements Runnable {
    //通过一个volatile变量来控制线程的停止
    private static volatile boolean flag = false;
    @Override
    public void run(){
        while(!flag){
            System.out.println("java多线程");
        }
    }

    public static void main(String[] args) throws InterruptedException {
       Thread t = new Thread(new TestThread());
       t.start();
       Thread.sleep(50);
       flag = true;
    }
}
复制代码

线程的中断

在java虚拟机中每个线程都有一个interrupt标识,表示线程是否中断,当线程处于WAITING或者TIMED_WAITING状态被中断的时候会抛出InterruptedException。java为中断提供了一些api,通过interrupt()方法中断线程,isInterrupted()方法可以知道线程是否被中断。 而中断标志也可以用来停止线程。

public class TestThread implements Runnable {

    @Override
    public void run(){
        //可以通过修改中断标志来停止线程
        while(!Thread.currentThread().isInterrupted()){
            System.out.println("java多线程");
        }
    }

    public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread(new TestThread());
        t.start();
        Thread.sleep(500);
        //修改中断标志为true
        t.interrupt();
    }
}
复制代码

结果如下:

1641023121(1).png

当线程处于WAITING或者TIMED_WAITING状态被中断的时候会抛出InterruptedException

结果如下:

1641022798(1).png

可以看到我们调用了interrupt()方法,线程并没有停止,这是因为InterruptedException会将interrupt重置 也就是恢复成false,这是因为现在在处于WAITING或者TIMED_WAITING状态时,这时候被中断 应该交给被中断的线程自己决定是否要中断。

不需要中断的时候可以不做处理 如果我们需要中断的时候可以在处理异常的时候再次调用interrupt()方法。

代码如下:

public class TestThread implements Runnable {

    private static volatile boolean flag = false;

    @Override
    public void run(){
        while(!Thread.currentThread().isInterrupted()){
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                //TODO 在中断前我们还可以做一些操作 比如关闭资源 保存数据等操作
                //确定要中断线程 调用interrupt()方法
                Thread.currentThread().interrupt();
                e.printStackTrace();
            }
            System.out.println("java多线程");
        }
    }

    public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread(new TestThread());
        t.start();
        Thread.sleep(500);
        t.interrupt();
    }
复制代码

结果如下:

1641023501(1).png

可以看出线程已经停止。

五 结束语

java多线程专栏将会对java.unit.current包中常用的一些并发工具进行介绍和源码的分析,本篇文章作为java多线程专栏的第一篇文章,主要介绍java线程的一些基础知识,如果大家对java多线程相关知识感兴趣的话可以收藏java多线程专栏。

Guess you like

Origin juejin.im/post/7048143497362145288