一、什么是Thread类
Thread类可以视为java标准库提供的一组解决多线程编程的一组API.创建好的Thread实例,和操作系统中的线程是一一对应的。操作系统提供了关于线程的API(C语言风格),java在对其进行封装就成Thread类。
二、线程的创建
2.1 继承Thread类
class MyThread extends Thread{
@Override
public void run() {
//此时只是定义处理一个线程类,在系统中总是还没有创建出 新的线程。
System.out.println("hello thread");
}
}
public class TestDemo11 {
public static void main(String[] args) {
//创建线程
Thread t = new MyThread();
//启动线程,在系统中创建出了新的线程
t.start();
}
}
2.2实现Runnable接口中的run()方法
//Runnable其实就是描述一个任务
//创建一个类,实现Runnable接口,重写Runnable类中的run方法,在run()方法中,描述的是该线程要指向的哪些任务。
class MyThread2 implements Runnable{
@Override
public void run() {
System.out.println("hello thread");
}
}
public class TestDemo12 {
public static void main(String[] args) {
//创建线程,把创建好的Runnable实例传给Thread实例
Thread t = new Thread(new MyThread2());
t.start();
}
}
2.3 利用匿名内部类
public class TestDemo14 {
public static void main(String[] args) {
Thread t1 = new MyThread(){
@Override
public void run() {
System.out.println("hello thread1");
}
};
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("hello thread2");
}
});
t1.start();
t2.start();
}
}
2.4 使用lambmd表达式
public class TestDemo15 {
public static void main(String[] args) {
//其实就是使用lambad表达式代替Runnable
Thread t1 = new Thread(()->{
//()表示无参的run()方法
System.out.println("hello thread1");
});
}
}
2.5 使用Callable为接口,创建线程
public static void main(String[] args) throws ExecutionException, InterruptedException {
// Callable为接口 创建个任务
Callable<Integer> callable = new Callable<Integer>() {
@Override
public Integer call() throws Exception {
int sum = 0;
for (int i = 0; i <= 1000; i++) {
sum += i;
}
return sum;
}
};
// 创建线程执行任务
// Thread不能直接传callable,需要在包装一层
FutureTask<Integer> futureTask = new FutureTask<>(callable);
Thread t = new Thread(futureTask);
t.start();
// get()获取上述任务结果
System.out.println(futureTask.get());
}
最常用的创建线程的方式为方法4,使用lambmd表达式。
定义出一个线程类,然后启动线程t.start(),其中start()方法决定系统是不是真的创建出线程。
三、线程中断
中断线程简单的可以理解成为就是让该线程中的run()方法执行结束。还有一个特殊的就是main线程,如果想要中断main线程,那么就需要把main线程执行完。
3.1 中断线程方法:设置一个标志位
public static boolean isQuit = false;
public static void main(String[] args) {
Thread t = new Thread(() ->{
while (!isQuit){
System.out.println("hello t");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(" t 线程终止");
});
t.start();
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
isQuit = true;
}
3.2 调用 interrupt() 方法来通知
使用
Thread.interrupted()
或者
Thread.currentThread().isInterrupted()
代替自定
义标志位
.
Thread 内部包含了一个 boolean 类型的变量作为线程是否被中断的标记.
public class TestDemo21 {
public static void main(String[] args) {
Thread t = new Thread(()->{
while(!Thread.currentThread().isInterrupted()) {
System.out.println("hello thread");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
//启动t线程
t.start();
//在main线程中中断t线程
//5s之后中断t线程
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
t.interrupt();
}
}
四 线程等待
使用join()方法,这个方法就是让线程与线程之间,有了一定的执行顺序。我们知道在多线程中的调度是随机的,不确定的,多线程的执行靠调度器安排,该调度器的安排是随机的,不规律的。其实线程等待就是一个行之有效的方法,实际上就是控制线程执行的先后顺序。
线程的等待 (Join())
//main线程调用join()时候,如果t还在运行,此时main线程阻塞,直到 t 执行完毕,main才从阻塞中解除,继续执行
//main线程调用join()时候,如果t已经结束,此时main立即执行
//都能保证 t 先执行
public static void main(String[] args) throws InterruptedException{
Thread t = new Thread(() ->{
System.out.println("hello t");
});
t.start();
t.join();
System.out.println("hello main");
}
五 线程的休眠
其实线程休眠就是调用Thread.sleep()方法。
public class ThreadDemo {
public static void main(String[] args) throws InterruptedException {
System.out.println(System.currentTimeMillis());
Thread.sleep(3 * 1000);
System.out.println(System.currentTimeMillis());
}
}
六、获取线程实例
一般我们就会通过Thread.currentThread()
来获取线程实例,在 Thread 类中,currentThread
是一个静态且本地方法。
public static void main(String[] args) {
// currentThread()是获取到当前线程的实例
//此处 currentThread 得到的对象就是 t
Thread t = new Thread(() ->{
while (!Thread.currentThread().isInterrupted()){
System.out.println("hello t");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
break;
}
}
System.out.println(" t 线程终止");
});
t.start();
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// interrupt()的作用
//把 t 内部的标志位设置成 ture
//如果该线程处于阻塞状态可以将该线程唤醒
t.interrupt();
}
运行结果: