Thread类的基本用法
线程创建
通过Thread类创建
通过继承 Thread 类并重写run方法就可以实现多线程;在 Thread 类中 提供了start方法启动新线程
class MyThread extends Thread{
public void run(){
System.out.println("MyThread中的run方法已执行");
}
}
public class Main{
public static void main(String[] args) {
MyThread t=new MyThread();
Thread thread=new Thread(t);
thread.start();
}
}
通过Runnable接口创建
java只支持单继承,如果一个类继承了某个父类就没办法再继承 Thread 类了,因此,Thread类提供了另一种构造方法Thread (Runnable target)构传的参数实现了Runnable接口的对象,Runnable接口中只有一个run方法,创建线程时实现Runnable接口中的run方法作为运行代码,不需要再调用Thread类中的run方法。
class MyThread implements Runnable{
public void run(){
System.out.println("Runnable接口创建的线程已运行");
}
}
public class Main{
public static void main(String[] args){
MyThread runnable=new MyThread();
Thread thread=new Thread(runnable);
thread.start();
}
}
通过Callable接口创建
在以上两种方法中创建线程的时候,里面的run方法都没有返回值,如果想要在run方法中获取返回值,就可以通过Callable接口来创建线程
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
import java.util.concurrent.ExecutionException;
class MyThread4 implements Callable<Object>{
@Override
public Object call() throws Exception {
System.out.println("call方法已执行");
return 0;
}
}
class Main{
public static void main(String[] args) throws ExecutionException, InterruptedException {
MyThread4 mt=new MyThread4();
FutureTask<Object> ft=new FutureTask<>(mt);
Thread thread=new Thread(ft,"thread");
thread.start();
//获取返回值
System.out.println(ft.get());
}
}
Callable 接口的实现的多线程是通过 FutureTask 类来进行封装和管理返回结果的,FutureTask 类的直接父接口是RunnableFuture,想必从名字我们就能看出它一定跟Runnable 接口有关系。RunnableFuture是Runnable和Future的结合体。看下图它们之间的关系:
在上图中我们可以看出,FutureTask是 Runnable 接口与 Future 接口的实现类。
线程创建的方式有多种,这里只列举了三种
其实严格来说,线程的创建方式只有通过new Thread().start()来创建,不管通过哪种方式最终都需要通过new Thread().start()创建。更加详细的描述可以看这篇文章大家都说Java有三种创建线程的方式!并发编程中的惊天骗局!
线程中断
线程中断指的是在线程运行过程中,手动中断线程的执行。
比如说,我写了一个多线程的代码,线程正在执行中,但是因为网速太辣鸡导致线程一直处于运行的状态,它不结束,我想停掉这个线程。
在 java 中执行线程中断有两个常用的方法:
- 通过共享的标记进行中断
- 使用 interrupt() 方法中断
第一种:
使用自定义的标志位
public class ThreadDemo {
private static class MyRunnable implements Runnable{
public volatile boolean isStop=false;
public void run(){
while(!isStop){
System.out.println(Thread.currentThread().getName()+"正在加载中……");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) throws InterruptedException {
MyRunnable target=new MyRunnable();
Thread thread=new Thread(target);
thread.start();
Thread.sleep(10*1000);
target.isStop=true;
System.out.println("线程已中断");
}
}
第二种:
使用 Thread.interrupted() 或者 Thread.currentThread().isInterrupted() 代替自定义标志位
public void interrupt() 中断对象关联的线程,如果线程正阻塞,通过异常来通知,否则设置标志位
public class ThreadDemo{
private static class MyRunnable implements Runnable{
@Override
public void run(){
while( !Thread.interrupted()){//或者 !Thread.interrupted()
System.out.println(Thread.currentThread().getName()+"正在加载中……");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.println("线程已中断");
break;
}
}
}
}
public static void main(String[] args) throws InterruptedException {
MyRunnable target=new MyRunnable();
Thread thread=new Thread(target);
thread.start();
Thread.sleep(10*1000);
thread.interrupt();
}
}
线程等待 -join()
有时候,我们想要在某个线程结束后再执行后面的任务,我们就需要线程等待,假如月光族张三想换个新手机,但是发现老板还没发工资,他就没钱买,只能等到老板发工资后再买
public class ThreadDemo3 {
public static void main(String[] args) throws InterruptedException {
Runnable runnable=()->{
for(int i=0;i<10;i++){
try {
System.out.println(Thread.currentThread().getName()+"没钱!");
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName()+"有钱了");
};
Thread thread1=new Thread(runnable,"老板");
Thread thread2=new Thread(runnable,"张三");
thread1.start();
thread1.join();
thread2.start();
thread2.join();
System.out.println("张三买到手机了");
}
}
线程休眠
让线程休眠的方法如下:
- public static void sleep(long millis) throws InterruptedException 休眠当前线程millis毫秒
- public static void sleep(long millis,int nanos)throws InterruptedException 更高精度的休眠
public class ThreadDemo1 {
public static void main(String[] args) throws InterruptedException {
System.out.println("当前时刻:"+System.currentTimeMillis());
Thread.sleep(3000);
System.out.println("当前时刻:"+System.currentTimeMillis());
}
}
获取线程实例
我们可以通过以下的方法进行获取:
public static Thread currentThread();
public class ThreadDemo {
public static void main(String[] args) {
Thread thread=Thread.currentThread();
System.out.println(thread);
}
}