關於Java的多線程Runnable的個人理解(基礎,不講概念)


背景說明:

在學了Java的多線程(繼承Thread,Runnable)以后,我出於好奇,就想知道java到底是不是多線程的,不能它說自己是多線程就是多線程,自己想驗證一下,於是我就想測試一下,但繼承Thread由於java的單繼承形式,導致不能生成多線程,但是Runnable可以,於是我就做了一個腳本(個人感覺一個java文件就是一個腳本,沒有上升到項目級別),我同時生成了10個線程,來模擬購票系統,假設一個線程模擬一個人去購10張票,一個人購買一張票的時間是0.5s(不可同時去購買兩張票及以上),然后觀察這100張票用多少時間購買完成。

所遇到的問題1:

問題描述:

首先就是計算一共用了多少時間了,我利用了如下圖的代碼框架來編寫,發現一個問題:因為當前java主程序也是一個線程,當主java程序在運行時,在創建完這10個線程后,主Java程序就執行完成了,它不會管這10個線程是否運行完成,在時間計算時,出現了問題。總時間會在線程運行時輸出(輸出的時間不是線程運行的時間)

解決步驟1:

解決方案如圖,解釋一下:我在接口實現類中定義了一個線程靜態共享變量,這個時候,當10個線程創建成功並運行,在最后一個線程運行完畢是對endTIme進行最后一次修改,該endTime就是這十個線程最后運行完成的時間,再進行時間計算。問題也就來了,還是沒有解決時間的統計,因為java主程序還是一個線程,時間輸出錯誤。

解決步驟2:

考慮到java主程序也是一個線程,我在創建10個線程后,立即休眠java 主線程(提前預估時間並設置相應的休眠時間),休眠時間稍微比線程運算預估時間大一點

最后:

時間問題解決,但是這個時候引發了一個大的問題,當10個線程在訪問同一個數據並修改時,數據可能發生異常。這個時候就需要線程對數據的互斥機制。

代碼:

主程序java代碼:javaThreadTest

package org.axc.com.javathread;

import java.util.Scanner;

/**
 * 
    * @ClassName: javaThreadTest
    * @Description: 測試java線程的運行
    * @author Anxc
    * @date 2019年8月8日
    *
 */
public class JavaThreadTest {
	public static void main(String[] args) {
//		線程的創建
		MyThread mythread;
		
		System.out.println("---------繼承Thread方式來實現創建線程-----------------");
		Scanner in = new Scanner(System.in);
		String menu="線程測試開始";
		int chioce=1;
		
		while(chioce!=0) {
			
			mythread = new MyThread();
			System.out.println("請輸入非0來開始調試繼承的Thread");
			System.out.print(">>");
			chioce = in.nextInt();
			if(chioce==0) {
				System.out.println("ByeBye");
				break;
			}
//			輸出菜單
			System.out.println(menu);
			
//			線程運行
			mythread.start();
		}
		
		System.out.println("------------利用Runnable接口實現創建線程-------------");
//		測試Runnable的多線程所用時間
		chioce = 1;
//		利用Runnable接口,初始化線程
		Runnable runnable = new MyRunnable();
		long startTime;
		long endTime;
		
		while(chioce!=0) {
			System.out.println("請輸入非0來開始調試");
			System.out.print(">>");
			chioce = in.nextInt();
			if(chioce == 0) {
				System.out.println("Runnable ByeBye!");
				break;
			}
			startTime = System.currentTimeMillis();
			System.out.println(startTime);
//			創建10個線程來觀察是否是真的多線程運行
			new Thread(runnable).start();
			  new Thread(runnable).start();
			  new Thread(runnable).start(); 
			  new Thread(runnable).start(); 
			  new Thread(runnable).start(); 
			  new Thread(runnable).start(); 
			  new Thread(runnable).start(); 
			  new Thread(runnable).start(); 
			  new Thread(runnable).start(); 
			  new Thread(runnable).start();
			  
			  Thread t=new Thread(runnable);
			  //t.isAlive();//判斷線程是否存活
			 try {
				Thread.sleep(8000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
//			輸出最后所用時間
			System.out.println("最終所用時間為:"+(((MyRunnable) runnable).getEndTime()-startTime));
		}
	}

}

實現接口Runnable的java程序代碼:MyRunnable

package org.axc.com.javathread;

/**
 * 
    * @ClassName: MyRunnable
    * @Description: 測試Runnable的真正多線程
    * @author Anxc
    * @date 2019年8月8日
    *
 */
public class MyRunnable implements Runnable {
	private static int count=100;    //加互斥鎖,當一個線程去修改值時,其它線程不能讀取
	public static long endTime;
	private static boolean flag=true;
	
	public MyRunnable() {
		
	}

	@Override
	public void run() {
		
		int num=10;
//		加鎖,使修改變量時只有一個線程在操作
		while(num>0) {
			if(flag) {
				flag=false;//加鎖
			count--;
			// TODO Auto-generated method stub
			System.out.println("當前剩余"+count);
			flag=true;//關鎖
			}
			else {
				try {
					Thread.sleep(10);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				continue;
				
			}
			try {
				Thread.sleep(500);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			num--;
		}
		
//		獲取線程運行終止時間
		endTime = System.currentTimeMillis();
//		System.out.println(endTime);
	}
	
	public long getEndTime() {
		return endTime;
		
	}

}

繼承Thread的方法的java程序:MyThread

package org.axc.com.javathread;

/**
 * 
    * @ClassName: MyThread
    * @Description: java線程的實現方式之一繼承Thread
    * @author Anxc
    * @date 2019年8月8日
    *
 */
public class MyThread extends Thread {
	private static int count = 0;
	public void run() {
		
		int num=0;
		count++;
		while(num<5) {
			System.out.println("再等等!"+count+num);
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			num++;
		}
		System.out.println("當前已經累計運行該線程:"+count+"次");
	}

}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM