线程,本身是操作系统提供的.操作系统提供了 API 让我们操作线程
JVM 就对 操作系统 api 进行了封装.线程这里,提供了 Thread 类, 表示线程
整个代码中有两个线程,thread线程还有main方法所在的线程即是主线程,
可以通过jvm中的jconsole工具来看到县城的运行
Thread.sleep(10000);
可以通过Thread睡眠来让线程进入阻塞状态
多个线程调度顺序是"无序"的,抢占式执行。
任何一个线程,在执行到任何一个代码的过程中,都可能被其他线程抢占掉它的 cpu 资源.于是 cpu 就给别的线程执行了.
start
1.new MyThread
调用 操作系统 提供的“创建线程”api在内核中创建对应 pcb,并且把 pcb 加入到链表中
进一步的系统调度到这个线程了之后,就会执行上述 run 方法中的逻辑!
public static void main(String[] args) throws InterruptedException {
Thread thread=new MyThread();//Thread自己记录、自己执行
thread.start();
thread.run();
Thread.sleep(10000);
}
}
class MyThread extends Thread{
@Override
public void run(){
//具体要干什么
System.out.println("hello thread");
}
此时 run 和主线程的循环是串行执行,不是"并发执行"。
像刚才谈到的 run, 只是定义好,而不去手动调用,把这个方法的调用,交给系统/其他的库/其他框架(别人)调用这样的方法(函数)称为"回调函数"(callback function)。
2.实现Runnable接口创建线程
public static void main(String[] args) {
Thread thread=new Thread(new MyRunnable());
thread.start();
thread.run();
while (true){
System.out.println("hello main");
}
}
}
class MyRunnable implements Runnable{
@Override
public void run(){
while (true){
System.out.println("hello thread");
try {
Thread.sleep(1100);
}catch (InterruptedException e){
e.printStackTrace();
}
}
}
Runnable 的作用,是描述了一个"任务’这个任务 和 具体的执行机制无关
刚才第一种写法, 是 Thread 自己记录我要干啥.自己记下来自己的作业。
第二种写法,通过 Runnable 记录作业是啥,Thread 负责执行,别人给你把作业记下来了,然后 Thread 负责执行。
他是通过Runnable来调用Thread这个类。
Runnable只要是为了解耦合,未来更换其他的方式来执行这些任务改动成本比较低。
3.匿名内部类
public class Test3 {
//匿名的线程
public static void main(String[] args) {
Thread t=new Thread(){
@Override
public void run(){
}
};
}
}
不是new Thread其实是几个操作的集合
1.创建了一个 Thread 的子类,(匿名)
2.同时创建了一个该子类的实例对于匿名内部类来说,只能创建这一个实例这个实例创建完了之后,再也拿不到这个匿名内部类了
3.此处的子类内部重写了父类的 run 方法
4.lambda表达式
public static void main(String[] args) {
Thread thread=new Thread(()->{
for (int i=0;i<3;i++){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
});
thread.start();
}