Java基础知识回顾--线程
基本概念
線程是一個程序內部的順序控制流
Java的線程是通過java.lang.Thread類來實現的。main函數是一個主線程,用戶可以通過創建Thread的實例來創建新的線程。每一個線程都必須實現run方法。通過Thread類的start方法來啟動一個線程。
兩種方式實現,一種是線程類實現Runnable接口;二種就是定義一個Thread的子類并重寫其run方法。
public class TestThread1 {public static void main(String args[]) {Runner1 r = new Runner1();r.start();//r.run();//Thread t = new Thread(r);//t.start();for(int i=0; i<100; i++) {System.out.println("Main Thread:------" + i);}} }//class Runner1 implements Runnable { class Runner1 extends Thread {public void run() {for(int i=0; i<100; i++) { System.out.println("Runner1 :" + i);}} }以下是幾個線程控制的基本方法
用stop或者其他方法直接切斷線程是很暴力的是很不好的,這里介紹一種比較好的結束線程的辦法。巧妙的用到一個flag。
public class TestThread4 { public static void main(String args[]){Runner4 r = new Runner4();Thread t = new Thread(r);t.start();for(int i=0;i<100000;i++){if(i%10000==0 & i>0)System.out.println("in thread main i=" + i);}System.out.println("Thread main is over");r.shutDown();//t.stop();} }class Runner4 implements Runnable {private boolean flag=true;public void run() {int i = 0;while (flag==true) {System.out.print(" " + i++); }}public void shutDown() {flag = false;} }線程同步
線程同步這個問題很重要,會衍生很多鎖的問題。也是兩種方式上鎖,一種是直接在方法上上鎖,另一種就是鎖對象。
死鎖
假如兩個線程都需要兩個資源才能完成,A線程把a資源鎖定等待b資源,B線程把b資源鎖定等待a資源。這樣就會形成死鎖,所以我們要把鎖定義到最大化就是鎖定整個對象,就是專業術語說鎖的粒度要盡量大。
這個程序段輸出的結果是
2000
b = 2000
這段程序也是先進的m2。
這段代碼輸出的結果是
1
2000
2
b = 1000
這一段代碼執行結果是
1000
b = 1000
鎖是鎖住了,但是tt那個線程執行的快一些,先進入了m2。
所以說線程同步是一個很復雜的問題,我們得仔細推敲。而且我個人覺得跟電腦的運行速度還是有關系的。其他線程可以自由訪問沒有加同步的任何方法,并且會產生數據不一致的現象。如果要保護好某一類的同步對象,必須要對該對象所有的方法考慮加不加同步,加了同步很有可能效率會變低,不加同步很有可能造成數據不一致的現象。
優先級
我的理解就是CPU優先讓哪個線程執行嘛,比較單CPU其實是假的多線程,就是因為CPU運算速度比較快,所以就一個線程讓你執行一下,就像是多線程在執行一樣。
生產者與消費者問題【經典問題】
public class ProducerConsumer {public static void main(String[] args) {SyncStack ss = new SyncStack();Producer p = new Producer(ss);Consumer c = new Consumer(ss);new Thread(p).start();new Thread(c).start();} }class WoTou {int id; WoTou(int id) {this.id = id;}public String toString() {return "WoTou : " + id;} }class SyncStack {int index = 0;WoTou[] arrWT = new WoTou[6];public synchronized void push(WoTou wt) {while(index == arrWT.length) {try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}}this.notifyAll(); arrWT[index] = wt;index ++;}public synchronized WoTou pop() {while(index == 0) {try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}}this.notifyAll();index--;return arrWT[index];} }class Producer implements Runnable {SyncStack ss = null;Producer(SyncStack ss) {this.ss = ss;}public void run() {for(int i=0; i<20; i++) {WoTou wt = new WoTou(i);ss.push(wt); System.out.println("生產了:" + wt);try {Thread.sleep((int)(Math.random() * 200));} catch (InterruptedException e) {e.printStackTrace();} }} }class Consumer implements Runnable {SyncStack ss = null;Consumer(SyncStack ss) {this.ss = ss;}public void run() {for(int i=0; i<20; i++) {WoTou wt = ss.pop(); System.out.println("消費了: " + wt);try {Thread.sleep((int)(Math.random() * 1000));} catch (InterruptedException e) {e.printStackTrace();} }} }總結
以上是生活随笔為你收集整理的Java基础知识回顾--线程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Android延时执行调用的几种方法
- 下一篇: C# 获取Excel中的合并单元格