java-多线程操作全(Thread)-Timer简单使用
?一、 多線程概念和作用
?線程指進程中的一個執行場景,也就是執行流程,那么進程和線程的區別是什么
? 1.每個進程是一個應用程序,都有獨立的內存空間
? 2.同一個進程中的線程共享其進程中的內存和資源
? (共享的內存是堆內存和方法內存,棧內存不共享,每個線程有自己的堆內存)
?進程:進程對應一個應用程序
? 現在的計算機都是支持多進程的,在同一個操作系統中,可以同時啟動多個進程?
??
?多進程的作用:
?* 單進程只能做一件事 : 一邊玩游戲,一邊聽音樂不是同時運行,而是進程之間的頻繁調度,切換速度極高,感覺是同時進行。
?* 多線程的作用不是提高執行速度,而是提高CPU的使用率。進程和進程之間的內存是獨立的、
?* 線程:是進程中的執行場景。一個進程可以啟動多個線程。
?* 多線程的作用:不是為了提高執行速度,而是為了提高應用程序的使用率
?
?* java程序的運行原理
?* java命令啟動java虛擬機,啟動JVM,等于啟動一個應用程序,表明啟動一個進程。該進程會自動啟動一個“主線程”,然后主線程去調用某各類的main方法。
?* 所以,main方法運行在主線程中。在此之前的所有程序都是單線程的。
?
?二、線程的創建和啟動
?
?*Java虛擬機的主線程入口是main方法,用戶可以自己創建線程,創建方式有兩種
?*1.繼承Thread類
?*2.實現Runnable接口(推薦使用Runnable)
?
?*繼承Thread類
?*采用 Thread類創建線程,用戶只需要繼承 Thread,覆蓋 Thread中的run方法,父類 Thread中的run方法沒有拋出異常,那么子類也不角能拋出異常,最后采用start啟動線程即可
?
?實現Runnable接口
?Thread對象本身就實現了 Runnable接口,但一般建議直接使用 Runnable接口來寫多線程程序,因為接口會比類帶來更多的好處
?
三、java語言中實現多線程第一種方式
?
1.繼承java.lang.Thread
2.重寫run方法
三個知識點 :定義線程 、創建線程、?啟動線程
package com.steven.demo;import java.lang.Thread; public class ThreadTest {public static void main(String[] args) {Thread thread = new Student();//啟動線程thread.start();//打印Run:0~9//start方法執行完瞬間結束,告訴JVM再分配一個新的線程 給t線程//是隨機分配的,沒有規律//run不需要手動調用,系統程序啟動之后會自動調用方法//thread.run();//這是普通方法的調用,這樣做程序只有一個線程,run方法結束之后,下邊的程序才會執行for (int i = 0; i < 5; i++) {System.out.println("main"+i);}//有了多線程之后,main方法結束只是主線程中沒有方法棧幀了 但是其他線程或者其他棧中還有棧幀 main方法結束,程序可能還在運行 } }class Student extends Thread {//重寫Run方法public void run() {for (int i = 0; i < 10; i++) {System.out.println("Run:"+i);}} }四、java語言中實現多線程第二種方式
1.寫一個類實現
2.重寫run方法
?
package com.steven.demo;import java.lang.Runnable; import java.lang.Thread; public class ThreadTest02 {public static void main(String[] args) {//創建線程:Thread thread = new Thread(new Teacher());//啟動線程 thread.start();} } class Teacher implements Runnable {//重寫Run方法public void run() {for (int i = 0; i < 10; i++) {System.out.println("Run:"+i);}} }五、掌握線程方法:
1.獲取當前線程的對象 Thread.currentThread()
2.給線程起名t.setName()
3.獲取線程的名字:t.getName()
?
package com.steven.demo; public class ThreadTest03 {public static void main(String[] args) {//獲取當前線程的對象 main主線程Thread thread = Thread.currentThread();//獲取當前線程的名字System.out.println("當前名稱的名稱"+thread.getName());//當前名稱的名稱main Thread t1 = new Thread(new ArrayTest());//給線程起名t1.setName("Steven");t1.start();//線程的名稱Steven Thread thread2 = new Thread(new ArrayTest());//給線程重命名thread2.setName("珂珂");thread2.start();//線程的名稱珂珂 } } class ArrayTest implements Runnable {public void run() {Thread thread = Thread.currentThread();//獲取當前線程的對象System.out.println("線程的名稱"+thread.getName());} }六、線程的優先級
優先級高的獲取CPU時間片,相對多一些
最高:10
最小:1
默認:5
優先級1-10
優先級高的線程,會得到CPU的時間多一些,優先執行完成
?
public class ThreadTest04 {public static void main(String[] args) {System.out.println("最高"+Thread.MAX_PRIORITY);System.out.println("最小"+Thread.MIN_PRIORITY);System.out.println("默認"+Thread.NORM_PRIORITY);Thread t1 = new Thread(new KeKe());t1.setName("t1");Thread t2 = new Thread(new KeKe());t2.setName("t2");//獲取線程的優先級System.out.println("t1優先級"+t1.getPriority());System.out.println("t2優先級"+t2.getPriority());//設置優先級t1.setPriority(5);t2.setPriority(6);//啟動 t1.start();t2.start();//線程雖然有優先級,但是隨機分配的,打印結果不一致 } } class KeKe extends Thread {public void run() {for (int i = 0; i < 10; i++) {System.out.println(Thread.currentThread().getName()+"----------------"+i);}} }七、線程休眠
①Thread.sleep()使當前正在執行的線程執行休眠操作(暫停執行) 單位:毫秒
sleep 靜態方法 作用: 阻塞當前線程,騰出CPU,讓給其他線程
public class ThreadTest05 {public static void main(String[] args) {Thread thread = new Array1();thread.setName("thread1");thread.start();//獲取當前線程的對象 main主線程Thread t = Thread.currentThread();//獲取當前線程的名字System.out.println("當前名稱的名稱"+t.getName());//當前名稱的名稱main //阻塞主線程for (int i = 0; i < 10; i++) {System.out.println(Thread.currentThread().getName() + "-------------------:" + i);try {Thread.sleep(2000);//程序休眠2秒鐘} catch (InterruptedException e) {// TODO Auto-generated catch block e.printStackTrace();}}} } class Array1 extends Thread {public void run() {System.out.println("線程正在啟動=-====");for (int i = 0 ; i < 5 ; i ++) {System.out.println(Thread.currentThread().getName() + "-------------------:" + i);try {Thread.sleep(2000);//程序休眠2秒鐘} catch (InterruptedException e) {// TODO Auto-generated catch block e.printStackTrace();}}} }②Thread.yield()暫停當前正在執行的線程對象,并執行其他線程。
?1.靜態方法
?2.作用:給同一個優先級的線程讓位,但是讓位時間不固定
?3.和sleep方法相同,就是yield的時間不固定
?他與sleep類似,只是不能由用戶執行暫停時間,并且yield()只能讓同優先級的線程有執行的機會
?
package com.steven.demo; public class ThreadTest07 {public static void main(String[] args) {//1.創建線程Thread thread = new HThread();thread.setName("線程07");//2.啟動線程 thread.start();//3.主線程for (int i = 0; i < 10; i++) {System.out.println(Thread.currentThread().getName() +"---------:"+i);}System.out.println("Steven=====");} } class HThread extends Thread {public void run() {for (int i = 0; i < 10; i++) {System.out.println(Thread.currentThread().getName() +"---------:"+i);if (i % 2 == 0) {//暫定當前線程,執行其他線程 Thread.yield();}}} }③線程的基本操作
/*線程的基本操作:創建,啟動,休眠,異常處理*/ public class ThreadTest06 {public static void main(String[] args) {try {//1.創建線程Thread thread = new MyThread();thread.setName("線程");//2.啟動線程 thread.start();//3.休眠Thread.sleep(2000);System.out.println("Steven=====");}catch (InterruptedException e) {e.printStackTrace();} } }class MyThread extends Thread {public void run() {for (int i = 0; i < 10; i++) {try {Thread.sleep(3000);} catch (Exception e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName() +"---------:"+i);}} }八、線程的合并(join)
public class ThreadTest08 {public static void main(String[] args) {try {//1.創建線程Thread thread = new KThread();thread.setName("線程07");//2.啟動線程 thread.start();//3.合并線程 (線程07和main線程合并)thread.join();//輸出只保證一個線程正在執行,依次執行,單線程的程序 (先執行線程07后執行main)//主線程for (int i = 0; i < 10; i++) {System.out.println(Thread.currentThread().getName() +"---------:"+i);} //當前線程可以調用第一個線程的join方法,調用后當前線程會被阻塞不再執行,直到被調用的線程執行完畢,當前線程才會執行} catch (InterruptedException e) {// TODO Auto-generated catch block e.printStackTrace();}} } class KThread extends Thread {public void run() {for (int i = 0; i < 10; i++) {try {Thread.sleep(2000);System.out.println(Thread.currentThread().getName() +"---------:"+i);} catch (InterruptedException e) {// TODO Auto-generated catch block e.printStackTrace();};}} }九、線程同步案例
<1>模擬取款:(不使用同步機制)多線程同時對同一個賬號進行取款操作
?
/* 模擬取款:不使用同步機制,多線程同時對同一個賬號進行取款操作 thread 和 thread2 異步編程模型:thread線程執行的是thread , thread2線程執行的是thread2 ,兩個線程之間誰也不等于誰 同步編程模型:thread線程和thread2線程執行,當thread線程必須等thread2的線程的執行結果之后,thread線程才能執行 ,這是同步編程什么時候需要引入同步: 1.為了數據安全,盡管程序的使用率低,但是為了保證數據安全性,必須得加入線程同步機制, 線程同步機制 使程序變成了單線程(一個線程) 2.在什么條件下需要使用線程同步 <1>必須是多線程環境 <2>多線程環境在共享同一個數據時 <3>共享的數據涉及到修改操作*/ package com.steven.demo;public class ThreadTest09 {public static void main(String[] args) {//創建一個公共的賬戶Account account = new Account("steven_kou",10000.0);//創建線程對同一個賬戶進行取款Thread thread = new Thread(new Money(account));thread.setName("steven");Thread thread2 = new Thread(new Money(account));thread2.setName("kou");thread.start();thread2.start();} }//取款線程 class Money implements Runnable {//賬戶 Account account;Money (Account account){this.account = account;}public void run() {account.withDraw(2000.0);System.out.println("取款2000.0$,余額為:"+account.getBalance());//取款2000.0$,余額為:8000.0 (輸出兩次) }}//銀行賬戶 class Account {private String actno;private double balance;//賬戶余額public Account() {}public Account(String actno,double balance) {this.actno = actno;//成員變量|局部變量this.balance = balance;}public void setActno(String actno) {this.actno = actno;}public String getActno() {return actno;}public void setBalance(double balance) {this.balance = balance;}public double getBalance() {return balance;}//對外提供一個取款方法public void withDraw(double money) {//對賬戶進行取款操作double after = balance - money;//延遲操作try {Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();//InterruptedException 線程中斷下拋出的異常 }this.setBalance(after);//更新賬戶余額,重新賦值 } }<2>模擬取款(同步機制,同步鎖synchronized)
①以下程序使用線程同步機制保證數據安全
?
package com.steven.demo; public class ThreadTest09 {public static void main(String[] args) {//創建一個公共的賬戶Account account = new Account("steven_kou",10000.0);//創建線程對同一個賬戶進行取款Thread thread = new Thread(new Money(account));thread.setName("steven");Thread thread2 = new Thread(new Money(account));thread2.setName("kou");thread.start();thread2.start();} }//取款線程 class Money implements Runnable {//賬戶 Account account;Money (Account account){this.account = account;}public void run() {account.withDraw(2000.0);System.out.println("取款2000.0$,余額為:"+account.getBalance());//取款2000.0$,余額為:8000.0 (輸出兩次) }}//銀行賬戶 class Account {private String actno;private double balance;//賬戶余額public Account() {}public Account(String actno,double balance) {this.actno = actno;//成員變量|局部變量this.balance = balance;}public void setActno(String actno) {this.actno = actno;}public String getActno() {return actno;}public void setBalance(double balance) {this.balance = balance;}public double getBalance() {return balance;}//對外提供一個取款方法//TODO 取款 同步public void withDraw(double money) {/*需要把同步的代碼,放到同步的語句塊中thread線程執行到此處,遇到了synchronized 關鍵字,就會去找this的對象鎖 如果找到了this的對象鎖,則進入同步語句塊 執行程序當同步語句塊代碼執行結束的時候,thread線程歸還this的對象鎖在thread線程執行同步語句塊的過程中,如果thread2線程也執行以下代碼。遇到synchronized 關鍵字,所以去找this對象鎖,但是該對象被thread線程持有, 只能等待thread線程使用完以后再解鎖this對象鎖*///同步鎖synchronized (this) {//對賬戶進行取款操作double after = balance - money;//延遲操作try {Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();//InterruptedException 線程中斷下拋出的異常 }//更新賬戶余額,重新賦值this.setBalance(after);}} }②synchronized關鍵字 添加到成員方法上,線程拿走的也是this對象鎖
//對外提供一個取款方法//TODO 取款 同步//synchronized關鍵字 添加到成員方法上,線程拿走的也是this對象鎖public synchronized void withDraw(double money) {/*需要把同步的代碼,放到同步的語句塊中thread線程執行到此處,遇到了synchronized 關鍵字,就會去找this的對象鎖 如果找到了this的對象鎖,則進入同步語句塊 執行程序當同步語句塊代碼執行結束的時候,thread線程歸還this的對象鎖在thread線程執行同步語句塊的過程中,如果thread2線程也執行以下代碼。遇到synchronized 關鍵字,所以去找this對象鎖,但是該對象被thread線程持有, 只能等待thread線程使用完以后再解鎖this對象鎖*///同步鎖 // synchronized (this) {//對賬戶進行取款操作double after = balance - money;//延遲操作try {Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();//InterruptedException 線程中斷下拋出的異常 }//更新賬戶余額,重新賦值this.setBalance(after); // }}?
三、守護線程
①定義一個用戶線程
package com.steven.demo;//定義一個用戶線程 public class UserThread01 {public static void main(String[] args) {Runnable runnable = new UserTest();Thread thread = new Thread(runnable, "UserThread");thread.start();for (int i = 0; i < 10; i++) {System.out.println(Thread.currentThread().getName() + "==== " + i);}System.out.println("主線程結束---");} }class UserTest implements Runnable {public void run() {for (int i = 0; i < 10; i++) {System.out.println(Thread.currentThread().getName() + "==== " + i);}} }?
②改為守護線程
package com.steven.demo; //守護線程 //其他所有的用戶線程結束,則守護線程退出 //守護線程一般都是無限執行的 守護線程最后結束(先執行用戶線程) //設置守護線程以后,當前主線程結束后,守護線程并沒有把所有的數據輸出就結束 也就是說 守護線程是為用戶線程服務的,當用戶線程全部結束,守護線程會自動化結束public class UserThread02 {public static void main(String[] args) {Thread thread = new UserTest02();thread.setName("thread");//將thread這個用戶線程 修改為守護線程thread.setDaemon(true);thread.start();//主線程 for (int i = 0; i < 10; i++) {System.out.println(Thread.currentThread().getName() + "==== " + i);try {Thread.sleep(1000);} catch (InterruptedException e) {// TODO Auto-generated catch block e.printStackTrace();}}System.out.println("主線程結束---");} } class UserTest02 extends Thread {public void run() {int i = 0;while (true) {i ++;System.out.println(Thread.currentThread().getName() +"====:"+i);try {Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}}} }四、定時器簡單使用:
?
package com.steven.demo;import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Timer; import java.util.TimerTask;/*Timer 定時器*/ public class TimerTest01 {public static void main(String[] args) {System.out.println("來了"); Timer timer = new Timer();try {Date date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2018-10-07 19:26:02");//安排在指定的時間執行指定的任務timer.schedule(new MyTimer(), date,1000*60*60*24);//date執行后續任務的時間間隔 設置定時任務:在2018-10-07 19:26:02執行此任務, 24小時執行一次//timer.schedule(new MyTimer(), date,1000*2);//如果設置每天執行一次:Date date = new SimpleDateFormat("HH:mm:ss").parse("19:26:02"); }catch (ParseException e) {e.printStackTrace();} catch (NullPointerException e) {e.printStackTrace();} catch (IllegalArgumentException e) {e.printStackTrace();} catch (IllegalStateException e) {e.printStackTrace();}} }class MyTimer extends TimerTask {public void run() {System.out.println("=="+new Date());//==Sun Oct 07 19:26:02 CST 2018 }}?
?
?
?
?
?
轉載于:https://www.cnblogs.com/StevenHuSir/p/Java_Thread.html
總結
以上是生活随笔為你收集整理的java-多线程操作全(Thread)-Timer简单使用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 抓包分析数据(Charles以及Http
- 下一篇: MATLAB代码:基于分布式优化的多产消