Artikel ini membawakan anda pengetahuan yang berkaitan tentang java, yang terutamanya mengatur isu yang berkaitan dengan utas A thread ialah laluan pelaksanaan dalam program yang biasa Kaedah ini sebenarnya adalah laluan pelaksanaan yang berasingan adalah hanya satu laluan pelaksanaan dalam program, maka program ini adalah program satu utas Mari kita lihat bersama-sama saya berharap ia akan membantu semua orang.
Kajian yang disyorkan: "tutorial video java"
Benang ialah laluan pelaksanaan dalam program yang kita panggil The familiar kaedah utama sebenarnya adalah laluan pelaksanaan yang berasingan Jika hanya terdapat satu laluan pelaksanaan dalam program, maka program itu ialah program satu utas kerana terdapat satu utas, terdapat juga berbilang benang . Makna literalnya boleh difahami. Ia adalah "teknologi yang melaksanakan pelbagai proses pada perisian dan perkakasan berbanding satu utas". Dalam program berbilang benang, apabila satu utas mesti menunggu, CPU boleh menjalankan utas lain dan bukannya menunggu, meningkatkan kecekapan program. Penciptaan berbilang benang Kaedah 1: Mewarisi kelas Thread
Tentukan subkelas MyThread Warisi kelas thread java.lang.Thread dan ganti kaedah run();
Buat objek kelas MyThread; Panggil objek utas Kaedah mula() memulakan utas (kaedah run() masih dilaksanakan selepas permulaan); yang merupakan benang utama kaedah utama Benang kanak-kanak dimulakan dengan memanggil start() dengan mythread objek benang. Tetapi mengapa hasil output tidak unik? Sebabnya ialah preemption CPU akan berlaku di antara dua utas semasa pelaksanaan, dan sesiapa yang merampasnya terlebih dahulu akan melaksanakan terlebih dahulu.
Jadi mengapa kita tidak terus menggunakan objek benang untuk memanggil kaedah run()? Jika run() dipanggil terus, ia hanyalah kaedah panggilan biasa, iaitu, satu utas, manakala kaedah start() digunakan untuk memulakan utas anak, supaya berbilang benang boleh berlaku.
public class ThreadDemo01 { public static void main(String[] args) { MyThread myThread1 = new MyThread(); myThread1.start(); for (int i = 0; i < 3; i++) { System.out.println("主线程正在执行~~"); } } } class MyThread extends Thread{ @Override public void run() { for (int i = 0; i < 3; i++) { System.out.println("子线程正在执行~~"); } } } //输出结果(不唯一): //主线程正在执行~~ //主线程正在执行~~ //主线程正在执行~~ //子线程正在执行~~ //子线程正在执行~~ //子线程正在执行~~
public class ThreadDemo02 { public static void main(String[] args) { MyRunnable target = new MyRunnable(); Thread thread = new Thread(target); thread.start(); for (int i = 0; i < 3; i++) { System.out.println("主线程正在执行~~"); } } } class MyRunnable implements Runnable{ @Override public void run() { for (int i = 0; i < 3; i++) { System.out.println("子线程正在执行~~"); } } } //输出结果(不唯一): //主线程正在执行~~ //子线程正在执行~~ //子线程正在执行~~ //子线程正在执行~~ //主线程正在执行~~ //主线程正在执行~~
该代码与方式一的不同之处在于需要将MyRunnable任务对象封装在Thread中,其他的地方是基本上是没有变化的。
方式二优缺点:
优点:线程任务类只是实现接口,可以继续继承类和实现接口,扩展性强;
缺点:编程多一层对象包装,如果线程有执行结果是不可以直接返回的。
接下来我们同样使用实现Runnable接口(匿名内部类形式)来实现多线程的创建:
1、创建Runnable匿名内部类对象;
2、交给Thread处理;
3、调用线程对象的start()启动线程;
//正常版: public class ThreadDemo01 { public static void main(String[] args) { Thread thread = new Thread(new Runnable() { @Override public void run() { for (int i = 0; i < 3; i++) { System.out.println("子线程正在执行~~"); } } }); thread.start(); for (int i = 0; i < 3; i++) { System.out.println("主线程正在执行~~"); } } } //lambda简化版: new Thread(()-> { for (int i = 0; i < 3; i++) { System.out.println("子线程正在执行~~"); } }).start();
该种方法从本质上其实并没有太大的区别只不过是一个需要创建线程对象,而另一个则是通过匿名内部类实现的多线程。并且该块代码也可以通过lambda表达式进行精简,不知道大家是否还对这个知识点有印象呢?若忘记了可以看一下这篇文章:Java中的lambda表达式如何理解——精简
在学习过前面两种创建多线程的方式以后,我们会发现存在一个问题:1、重写的run()方法不能直接返回结果;2、不适合需要返回线程执行结果的业务场景。因此,我们需要第三种方式来解决这些问题。
方式三创建过程:
1、定义类实现Callable接口,重写call()方法,封装要做的事情;
2、用FutureTask把Callable对象封装成线程任务对象;
3、把线程任务对象交给Thread处理;
4、调用Thread的start()方法启动线程,执行任务;
5、线程执行完毕后,通过FutureTask的get()方法获取任务执行的结果。
方法名称 | 说明 | |
public FutureTask<>(Callable call) | 把Callable对象封装成FutureTask对象 | |
public V get() throws Exception | 获取线程执行call方法返回的结果 |
方式 | 优点 | 缺点 |
继承Thread类 | 编程比较简单,可以直接使用Thread类中的方法 | 扩展性较差,不能再继承其他的类,不能返回线程执行的结果 |
实现Runnable接口 | 扩展性强,实现该接口的同时还可以继承其他的类 | 编程相对复杂,不能返回线程执行的结果 |
实现Callable接口 | 扩展性强,实现该接口的同时还可以继承其他的类,可以得到线程的执行结果 | 编程相对复杂 |
方法名称 | 说明 |
String getName() | 获取当前线程的名称,默认线程名称是Thread-索引 |
void setName(String name) | 将此线程更改为指定的名称,通过构造器也可以设置线程名称 |
简单地通过一段代码让大家能够清晰地了解这个代码该如何使用:
public class ThreadDemo04 { public static void main(String[] args) throws Exception { thread thread1 = new thread(); thread1.setName("1号子线程"); thread1.start(); thread thread2 = new thread(); thread2.setName("2号子线程"); thread2.start(); } } class thread extends Thread { @Override public void run() { for (int i = 0; i < 3; i++) { System.out.println(this.getName()+"正在执行任务"+i); } } } //输出结果: //2号子线程正在执行任务0 //1号子线程正在执行任务0 //2号子线程正在执行任务1 //1号子线程正在执行任务1 //2号子线程正在执行任务2 //1号子线程正在执行任务2
方法名称 | 说明 |
public static void sleep(long time) | 让当前线程休眠指定的时间后再继续执行,单位为毫秒 |
public class ThreadDemo05 { public static void main(String[] args) throws Exception { for (int i = 0; i < 5; i++) { System.out.println(i); if (i==3){ Thread.sleep(5000); } } } } //输出结果: //1 //2 //3 //在输出过3以后,等待5秒之后再进行输出 //4
推荐学习:《java视频教程》
Atas ialah kandungan terperinci Satu artikel untuk memahami cara memahami benang dalam Java. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!