启动线程
在运行线程之前首先要构造一个线程对象,线程对象在构造的时候需要提供线程的属性,比如线程组、优先级、名字、Daemon状态啊等属性。
一个新构造的线程对象初始化好了,在堆内存中等待着运行。调用 start() 方法就可以启动这个线程。线程的 start() 方法的含义是:当前线程同步告知 Java虚拟机,只要线程规划器空闲,应立即启动调用 start() 方法的线程。
🌔 注意,启动一个线程,最好为这个线程设置线程名称,因为这样在使用 jstack 分析线程或者进行问题排查时,就会给我们提供一些提示。
线程终止
中断可以理解为线程的一个标识位属性,它表示一个运行中的线程是否被其它线程进行了中断。中断好比其它线程对该线程打了个招呼,其他线程通过调用该线程的 interrupt() 方法对其进行中断操作。
线程通过检查自身是否被中断进行响应,线程通过方法 isInterrupted() 来进行判断是否被中断,也可调用静态方法 Thread.interrupted() 对当前线程的中断标识位进行复位。如果该线程已经处于终结状态,即使该线程被中断过,在调用该线程对象的 isInterrupted() 时依旧会返回 false。
如下代码,显示一个终止线程用例:
public class ThreadInterrupt {
public static void main(String[] args){
Thread t1 = new Thread(new MyThread(),"精灵线程");
t1.start();
try {
//main线程休眠10毫秒
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
//终止精灵线程
t1.interrupt();
}
}
class MyThread implements Runnable{
private long i=0;
@Override
public void run() {
while (!Thread.currentThread().isInterrupted()) {
i++;
}
System.out.println(Thread.currentThread().getName()+" 运行10毫秒,i 值累加结果:"+i);
}
}
main方法创建了一个名为“精灵线程” t1,休眠10毫秒后,对 t1 线程进行终止。
其输出结果(每次可能都不一样):
精灵线程 运行10毫秒,i 值累加结果:1054662
实现线程3种方式
实现Runable接口
接口需要实现run方法,在run方法体内编写内容,用例代码如下:
package cn.zealon.thread;
import java.util.Date;
/**
* 实现Runnable接口,需要实现 run() 方法。
*
* @auther: Zealon
*
*/
public class UseRunnable implements Runnable{
@Override
public void run() {
System.out.println("当前线程名称:"+Thread.currentThread().getName()+
",时间:"+new Date().toString());
}
//运行线程实例
public static void main(String[] args) {
UseRunnable instance = new UseRunnable();
Thread thread = new Thread(instance);
thread.start();
}
}
继承Thread类
继承Thread类,需要重写run方法,因为Thread类也实现了Runable 接口,我们可以看下Thread类的定义如下:
/**
* A <i>thread</i> is a thread of execution in a program. The Java
* Virtual Machine allows an application to have multiple threads of
* execution running concurrently.
* <p>
* ......
* @author unascribed
* @see Runnable
* @see Runtime#exit(int)
* @see #run()
* @see #stop()
* @since JDK1.0
*/
public class Thread implements Runnable {
/* Make sure registerNatives is the first thing <clinit> does. */
private static native void registerNatives();
static {
registerNatives();
}
...
}
Thread类相当于封装了一些并发相关的属性以及方法,它自身实现的Runnable接口,所以我们继承Thread类需要重写run方法,用例代码如下:
package cn.zealon.thread;
import java.util.Date;
/**
* 继承Thread类,需要重写run方法(因为Thread类也实现了Runable 接口).
*
* @auther: Zealon
*/
public class UseThread extends Thread{
@Override
public void run() {
System.out.println("当前线程名称:"+Thread.currentThread().getName()+
",时间:"+new Date().toString());
}
public static void main(String[] args){
UseThread instance = new UseThread();
instance.start();
}
}
实现Callable接口
实现Callable接口,需要实现call方法;与Runnable方式比较,Callable方式有返回值,返回值通过FutureTask进行封装。 用例代码如下:
package cn.zealon.thread;
import java.util.Date;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
/**
* 实现Callable接口,需要实现call方法;
* 与Runnable方式比较,Callable方式有返回值,返回值通过FutureTask进行封装.
*
* @auther: Zealon
*
*/
public class UseCallable implements Callable<String> {
@Override
public String call() {
return "当前时间:"+new Date().toString();
}
public static void main(String[] args){
UseCallable instance = new UseCallable();
//封装任务类
FutureTask<String> futureTask = new FutureTask<String>(instance);
//创建线程类
Thread thread = new Thread(futureTask);
//启动线程
thread.start();
try {
System.out.println(futureTask.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
作者: Zealon
崇尚简单,一切简单自然的事物都是美好的。