一:简述
由于有的读者反馈我多线程的专栏应该从基础基础讲起,所以本篇文章就补上多线程相关的基础知识,当做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()方法执行完成会进入该状态。
三: 线程的创建
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();
}
}
复制代码
结果如下:
当线程处于WAITING或者TIMED_WAITING状态被中断的时候会抛出InterruptedException
结果如下:
可以看到我们调用了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();
}
复制代码
结果如下:
可以看出线程已经停止。
五 结束语
java多线程专栏将会对java.unit.current包中常用的一些并发工具进行介绍和源码的分析,本篇文章作为java多线程专栏的第一篇文章,主要介绍java线程的一些基础知识,如果大家对java多线程相关知识感兴趣的话可以收藏java多线程专栏。