基本概念
线程是一个程序内部的顺序控制流
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;}
}
线程同步
线程同步这个问题很重要,会衍生很多锁的问题。也是两种方式上锁,一种是直接在方法上上锁,另一种就是锁对象。
public class TestSync implements Runnable {Timer timer = new Timer();public static void main(String[] args) {TestSync test = new TestSync();Thread t1 = new Thread(test);Thread t2 = new Thread(test);t1.setName("t1"); t2.setName("t2");t1.start(); t2.start();}public void run(){timer.add(Thread.currentThread().getName());}
}class Timer{private static int num = 0;public synchronized void add(String name){ //synchronized (this) {num ++;try {Thread.sleep(1);} catch (InterruptedException e) {}System.out.println(name+", 你是第"+num+"个使用timer的线程");//}}
}
死锁
假如两个线程都需要两个资源才能完成,A线程把a资源锁定等待b资源,B线程把b资源锁定等待a资源。这样就会形成死锁,所以我们要把锁定义到最大化就是锁定整个对象,就是专业术语说锁的粒度要尽量大。
public class TT implements Runnable {int b = 100;public synchronized void m1() throws Exception{//Thread.sleep(2000);b = 1000;Thread.sleep(5000);System.out.println("b = " + b);}public void m2() throws Exception{Thread.sleep(2500);b = 2000;}public void run() {try {m1();} catch(Exception e) {e.printStackTrace();}}public static void main(String[] args) throws Exception {TT tt = new TT();Thread t = new Thread(tt);t.start();tt.m2();System.out.println(tt.b);}
}
这个程序段输出的结果是
2000
b = 2000
这段程序也是先进的m2。
package yanning;public class TT implements Runnable {int b = 100;public synchronized void m1() throws Exception{System.out.println(2);//Thread.sleep(2000);b = 1000;Thread.sleep(5000);System.out.println("b = " + b);}public synchronized void m2() throws Exception {System.out.println(1);Thread.sleep(2500);b = 2000;}public void run() {try {m1();} catch(Exception e) {e.printStackTrace();}}public static void main(String[] args) throws Exception {TT tt = new TT();Thread t = new Thread(tt);t.start();tt.m2();System.out.println(tt.b);}
}
这段代码输出的结果是
1
2000
2
b = 1000
package yanning;public class TT implements Runnable {int b = 100;public synchronized void m1() throws Exception{//System.out.println(2);//Thread.sleep(2000);b = 1000;Thread.sleep(5000);System.out.println("b = " + b);}public synchronized void m2() throws Exception {//System.out.println(1);Thread.sleep(2500);b = 2000;}public void run() {try {m1();} catch(Exception e) {e.printStackTrace();}}public static void main(String[] args) throws Exception {TT tt = new TT();Thread t = new Thread(tt);t.start();tt.m2();System.out.println(tt.b);}
}
这一段代码执行结果是
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();} }}
}