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);
        }
    }
}

以下是几个线程控制的基本方法
Java基础知识回顾--线程

用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();
            }           
        }
    }
}
上一篇:CSS3 overflow-x 属性


下一篇:联想G480类似没有小键盘开关的机器