kaedah $start()$ digunakan untuk memulakan thread Pada masa ini, thread sudah sedia Keadaan (Boleh Dijalankan), tidak berjalan Setelah kepingan masa $cpu$ diperoleh, kaedah $run()$ mula dilaksanakan. Memanggil kaedah $run()$ secara langsung hanya memanggil kaedah dalam kelas, yang pada asasnya dilaksanakan dalam urutan semasa Oleh itu, ia hanya boleh dicapai dengan menggunakan kaedah $start()$ untuk memanggil $run()$ kaedah multithreading sebenar.
@Slf4j(topic = "c.Test4") public class Test4 { public static void main(String[] args) { Thread t1 = new Thread("t1"){ @Override public void run() { log.debug("running"); } }; t1.run(); } }
Kod di atas ialah kaedah $run()$ yang dipanggil terus. Anda boleh melihat dalam maklumat bercetak bahawa benang $main$ melaksanakan kaedah ini.
@Slf4j(topic = "c.Test4") public class Test4 { public static void main(String[] args) { Thread t1 = new Thread("t1"){ @Override public void run() { log.debug("running"); } }; t1.start(); } }
Dan jika anda menggunakan kaedah $start()$ untuk memulakan, ia ialah kaedah $run$ sebenar yang dilaksanakan oleh thread $t1$.
Perlu diambil perhatian bahawa apabila objek $Thread$ memanggil kaedah $start()$, ia akan memasuki keadaan sedia Apabila ia berada dalam keadaan sedia, $start () tidak boleh dipanggil semula kaedah $, jika tidak, pengecualian $IllegalThreadStateException$ akan dibuang, seperti yang ditunjukkan dalam kod berikut
@Slf4j(topic = "c.Test4") public class Test4 { public static void main(String[] args) { Thread t1 = new Thread("t1"){ @Override public void run() { log.debug("running"); } }; t1.start(); t1.start(); } }
Maklumat pengecualian:
Memanggil kaedah $sleep()$ akan menukar urutan semasa daripada $Running$ nyatakan kepada keadaan $Time Waiting$ (menyekat)
Urutan lain boleh menggunakan kaedah $interrupt$ untuk mengganggu utas tidur Pada masa ini, kaedah $sleep$ akan membuang InterruptedException
Tidur Urutan selepas siap mungkin tidak dilaksanakan serta-merta
Adalah disyorkan untuk menggunakan $TimeUnit$'s $sleep$ dan bukannya $ $sleep$ Thread$ untuk mendapatkan kod sampel kebolehbacaan yang lebih baik
@Slf4j(topic = "c.Test5") public class Test5 { public static void main(String[] args) { Thread t1 = new Thread("t1"){ @Override public void run() { try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } } }; t1.start(); log.debug("t1 state {}", t1.getState()); //让主线程休眠500ms try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } log.debug("t1 state {}", t1.getState()); } } //17:13:21.729 [main] DEBUG c.Test5 - t1 state RUNNABLE //17:13:22.245 [main] DEBUG c.Test5 - t1 state TIMED_WAITING
Dalam kod di atas, utas $t1$ mula-mula dimulakan pada masa ini benang pencetakan hendaklah dalam keadaan $RUNNABLE$, dan membiarkan utas utama tidur adalah untuk menghalang utas utama daripada melaksanakan pencetakan dahulu, tetapi belum lagi memasuki keadaan $sleep()$. Apabila kaedah $sleep$ dalam $run()$ dilaksanakan, utas memasuki keadaan $TIMED WAITING$
@Slf4j(topic = "c.Test6") public class Thread6 { public static void main(String[] args) throws InterruptedException { Thread t1 = new Thread("t1") { @Override public void run() { try { log.debug("enter sleep"); Thread.sleep(2000); } catch (InterruptedException e) { log.debug("wake up"); e.printStackTrace(); } } }; t1.start(); Thread.sleep(1000); log.debug("interrupt t1"); //被唤醒 t1.interrupt(); } }
Hasil pelaksanaan
Dalam kod di atas, apabila kaedah $start$ dimulakan, benang $t1$ memasuki keadaan tidur, mencetak maklumat segera, masa tidur ialah $2s$ dan terganggu dalam $main$ benang selepas tidur untuk $1s$ Apabila benang t1$ tidur, mesej gangguan digesa dan kaedah $interrupt()$ dipanggil.
Kelas $TimeUnit$ telah menambah unit untuk tidur, yang lebih mudah dibaca, tetapi pada asasnya tiada perbezaan, hanya penukaran unit
TimeUnit.SECONDS.sleep(1);//该语句作用是睡眠一秒
Panggil $ Hasil $ akan menyebabkan proses semasa memasuki $ Runnable $ Ready State dari $ Running $, dan kemudian menjadualkan dan melaksanakan thread lain. system, ( Iaitu, apabila tiada tugas lain dalam penjadual tugas, walaupun $cpu$ telah diserahkan, benang akan terus dilaksanakan) $sleep$ akan memasuki keadaan menyekat selepas pelaksanaan Pada masa ini, jika masa tidur tidak tamat, $cpu$ tidak akan diperuntukkan kepada utas ini, tetapi $yield$ memasuki keadaan sedia, iaitu, jika tiada utas lain perlu dilaksanakan, utas itu juga akan diperuntukkan kepingan masa perbezaan terbesar antara $sleep$ dan $yield$ Keutamaan utas
akan menggesa penjadual menjadualkan utas dahulu, tetapi ia hanya gesaan dan penjadual boleh mengabaikannya<. 🎜>Jika $cpu$ sibuk, yang mempunyai keutamaan yang lebih tinggi akan mendapat lebih banyak masa, tetapi apabila $cpu$ melahu, keutamaannya hampir tidak (benar)$ Melahu membazir $cpu$ Pada masa ini, anda boleh menggunakan $yield$ atau $sleep$ untuk menyerahkan penggunaan $cpu$ kepada program lain
$sleep$ sesuai untuk senario yang tidak memerlukan penyegerakan kunci
while (true) { try { Thread.sleep(50); } catch (InterruptedException e) { e.printStackTrace(); } }
Cetak hasil program berikut:
Oleh kerana utas utama dan benang $t1$ selari, ia memerlukan $1s$ untuk benang $t1$ mengira nilai $r$, dan utas utama mencetak nilai $r$ pada permulaan, jadi nilai yang dicetak ialah 0
@Slf4j(topic = "c.Test6") public class Test6 { static int r = 0; public static void main(String[] args) { test(); } private static void test() { log.debug("开始"); Thread t = new Thread("t1") { @Override public void run() { log.debug("开始"); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } log.debug("结束"); r = 10; } }; t.start(); log.debug("r的值是{}", r); log.debug("结束"); } }
Penyelesaian:
Dari perspektif pemanggil, adalah segerak untuk menunggu keputusan dikembalikan sebelum meneruskan pelaksanaan, dan adalah tidak segerak untuk meneruskan pelaksanaan tanpa menunggu keputusan dikembalikan.
Jadi kaedah $join$ sebenarnya membenarkan ia dilaksanakan secara serentak
dengan penantian yang berkesan
打断$sleep, wait, join$的线程,即打断阻塞状态的线程
打断$sleep$的线程,会清空打断状态
@Slf4j(topic = "c.Test7") public class Test7 { public static void main(String[] args) throws InterruptedException { Thread t = new Thread("t1"){ @Override public void run() { log.debug("sleep..."); try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } } }; t.start(); Thread.sleep(1000); log.debug("interrupt"); t.interrupt(); log.debug("打断标记: {}", t.isInterrupted()); } }
因此我们可以在线程中判断打断标记,来决定是否被打断,以及执行被打断之前的收尾工作。
@Slf4j(topic = "c.Test8") public class Test8 { public static void main(String[] args) throws InterruptedException { Thread t = new Thread("t1"){ @Override public void run() { while (true) { if (Thread.currentThread().isInterrupted()) { log.debug("线程被打断了"); break; } } } }; t.start(); Thread.sleep(1000); log.debug("interrupt"); t.interrupt(); } }
默认情况下,$java$需要等待所有线程都运行结束,才会结束。有一种特殊的线程叫做守护线程,只要其他非守护线程运行结束了,即使守护线程的代码没有执行完毕,也会强制结束。
@Slf4j(topic = "c.Test10") public class Test10 { public static void main(String[] args) throws InterruptedException { Thread t = new Thread("t1") { @Override public void run() { while (true) { } } }; //设置线程为守护线程 t.setDaemon(true); t.start(); Thread.sleep(1000); log.debug("主线程结束"); } }
如果不把$t$设置为守护线程,则因为线程内部的死循环,导致程序不会结束运行。
Atas ialah kandungan terperinci Cara menggunakan kaedah mula dan kaedah jalankan dalam benang Java. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!