Java 多线程

Thread

sample

 class MyThread extends Thread {        private String name;    public MyThread(String name) {        this.name = name;    }    @Override    public void run() {        //.....    } } class Main {    public static void main(String[] args) {        MyThread a = new MyThread('A');        MyThread b = new MyThread('B');        a.start();        b.start();    } }

start 方法不能重复调用, 重复调用会出现java.lang.IllegalThreadStateException异常

Runnable

sample

 class MyRunnable extend Runnable{    public MyRunnable() {    }    @Override    public void run() {    } } class Main {    public static void main(String[] args) {        MyRunnable a = new MyRunnable('A');        MyRunnable b = new MyRunnable('B');        Thread demoa = new Thread(a);        Thread demob = new Thread(b);        demoa.start();        demob.start();    } }

关于选择继承Thread还是实现Runnable接口?

其实Thread也是实现Runnable接口的:

 class Thread implements Runnable {    //…    public void run() {        if (target != null) {             target.run();        }    } }

Thread中的run方法调用的是Runnable接口的run方法。Thread和Runnable都实现了run方法,这种操作模式其实就是代理模式。

Thread和Runnable的区别

如果一个类继承Thread,则不适合资源共享。但是如果实现了Runable接口的话,则很容易的实现资源共享。

class MyThread implements Runnable{     private int ticket = 5;  //5张票     public void run() {        for (int i=0; i<=20; i++) {            if (this.ticket > 0) {                System.out.println(Thread.currentThread().getName()+ "正在卖票"+this.ticket--);            }        }    }}public class lzwCode {         public static void main(String [] args) {        MyThread my = new MyThread();        new Thread(my, "1号窗口").start();        new Thread(my, "2号窗口").start();        new Thread(my, "3号窗口").start();    }}

实现Runnable接口比继承Thread类所具有的优势:

1):适合多个相同的程序代码的线程去处理同一个资源
2):可以避免java中的单继承的限制
3):增加程序的健壮性,代码可以被多个线程共享,代码和数据独立。

主线程和子线程之间的关系

在java中,每次程序运行至少启动2个线程。一个是main线程,一个是垃圾收集线程。因为每当使用java命令执行一个类的时候,实际上都会启动一个JVM,每一个jVM就是在操作系统中启动了一个进程。

主线程也有可能在子线程结束之前结束。并且子线程不受影响,不会因为主线程的结束而结束。

    // 休眠两秒    Thread.sleep(2000);    // 强制加入    thread.join();    // 后台线程    thread.setDaemon(true);    /**     * @author Rollen-Holt 后台线程     * */    class hello implements Runnable {        // 虽然有一个死循环,但是程序还是可以执行完的。因为在死循环中的线程操作已经设置为后台运行了。        public void run() {            while (true) {                System.out.println(Thread.currentThread().getName() + "在运行");            }        }             public static void main(String[] args) {            hello he = new hello();            Thread demo = new Thread(he, "线程");            demo.setDaemon(true);            demo.start();        }    }    // 优先级    // 不要误以为优先级越高就先执行。谁先执行还是取决于谁先去的CPU的资源。    thread.setPriority(8);    // 礼让    // 在线程操作中,也可以使用yield()方法,将一个线程的操作暂时交给其他线程执行。    Thread.currentThread().yield();

同步和死锁

/** * @author Rollen-Holt * */class hello implements Runnable {    public void run() {        for(int i=0;i<10;++i){            if(count>0){                try{                    Thread.sleep(1000);                }catch(InterruptedException e){                    e.printStackTrace();                }                System.out.println(count--);            }        }    }     public static void main(String[] args) {        hello he=new hello();        Thread h1=new Thread(he);        Thread h2=new Thread(he);        Thread h3=new Thread(he);        h1.start();        h2.start();        h3.start();    }    private int count=5;} //【运行结果】: // 5  // 4 // 3 // 2 // 1 // 0 // -1

这里出现了-1,显然这个是错的。应该票数不能为负值。
如果想解决这种问题,就需要使用同步。所谓同步就是在统一时间段中只有有一个线程运行,其他的线程必须等到这个线程结束之后才能继续执行。

使用线程同步解决问题

使用同步代码块同步方法

同步代码块

    synchronized(同步对象){        //需要同步的代码    }
/** * @author Rollen-Holt * */class hello implements Runnable {    public void run() {        for(int i=0;i<10;++i){            synchronized (this) {                if(count>0){                    try{                        Thread.sleep(1000);                    }catch(InterruptedException e){                        e.printStackTrace();                    }                    System.out.println(count--);                }            }        }    }     public static void main(String[] args) {        hello he=new hello();        Thread h1=new Thread(he);        Thread h2=new Thread(he);        Thread h3=new Thread(he);        h1.start();        h2.start();        h3.start();    }    private int count=5;}

同步方法

 synchronized 方法返回类型方法名(参数列表){    // 其他代码 }
/** * @author Rollen-Holt * */class hello implements Runnable {    public void run() {        for (int i = 0; i < 10; ++i) {            sale();        }    }     public synchronized void sale() {        if (count > 0) {            try {                Thread.sleep(1000);            } catch (InterruptedException e) {                e.printStackTrace();            }            System.out.println(count--);        }    }     public static void main(String[] args) {        hello he = new hello();        Thread h1 = new Thread(he);        Thread h2 = new Thread(he);        Thread h3 = new Thread(he);        h1.start();        h2.start();        h3.start();    }     private int count = 5;}

死锁

当多个线程共享一个资源的时候需要进行同步,但是过多的同步可能导致死锁。

生产者,消费者问题

/* *面包类,用于存放厨师生产的面包 */public class Bread {    private String producer;    public Bread(String producer) {        super();        this.producer = producer;    }    @Override    public String toString() {        return producer;    }} /*  * 篮子类,用于存放面包  * 篮子假定最多放10个面包  */  public class Basket {      private int index = 0;      private Bread[] arrayBread = new Bread[10];        /*      * 此方法用于往篮子里扔面包 每当厨师生成好一个面包就往篮子里边扔 由于当某一个厨师在往篮子扔面包的过程(还没扔完,但是面包已经在篮子里),      * 又有一个厨师要往篮子里扔面包。 如果这是篮子里已经有9个面包的话,最后一个厨师就不能在扔了。      * 所以需要给这个方法加把锁,等一个厨师扔完后,另外一个厨师才能往篮子里扔。      */      public synchronized void push(int id, Bread bread) {          System.out.println("生成前篮子里有面包:" + index + " 个");          // 当厨师发现篮子满了,就在那里不停的等着          while (index == arrayBread.length) {              System.out.println("篮子满了,我开始等等。。。。。。");              try {                  // 厨师(一个生产线程)开始不停等待                  // 他需要等待顾客(一个消费线程)把它叫醒                  this.wait();              } catch (InterruptedException e) {                  e.printStackTrace();              }          }            // 唤醒一个正在等待的线程,如果唤醒的线程为生产线程,则又会进入等待状态,          // 如果为消费线程,则因生产线程生产了面包的缘故,消费线程可以进行消费          this.notify();          arrayBread[index] = bread;          index++;          System.out.println(bread);        }        /*      * 此方法用于往篮子里拿面包 加锁原因和上边一样      */      public synchronized Bread pop(int id) {          System.out.println("消费前篮子里有面包:" + index + " 个");          while (index == 0) {              System.out.println("篮子空了,我开始等等。。。。。。");              try {                  // 顾客(一个消费线程)开始不停等待                  // 他需要等待厨师(一个生产线程)把它叫醒                  this.wait();              } catch (InterruptedException e) {                  e.printStackTrace();              }          }            // 唤醒一个正在等待的线程,如果唤醒的线程为消费线程,则又会进入等待状态,          // 如果为生产线程,则因生产线程消费了面包的缘故,生产线程可以进行生产          this.notify();          index--;          System.out.println("第" + id + "个顾客消费了 -->" + arrayBread[index]);          return arrayBread[index];      }  }/*  * 厨师类,用于生产面包  */  public class Kitchener implements Runnable {      private Basket basket;      private int id;        public Kitchener(int id,Basket basket) {          super();          this.id = id;          this.basket = basket;      }        @Override      public void run() {          //让厨师生产10个面包          for (int i = 1; i <= 10; i++) {              Bread bread = new Bread("第" + id + "个厨师生成的面包");              basket.push(id,bread);                                          try {                  Thread.sleep(1);              } catch (InterruptedException e) {                  // TODO Auto-generated catch block                  e.printStackTrace();              }          }        }    }  /*  * 顾客类,用于消费面包  */  public class Customer implements Runnable {      private Basket basket;      private int id;      public Customer(int id,Basket basket) {          super();          this.id = id;          this.basket = basket;      }        @Override      public void run() {          // 让顾客消费10个面包          for (int i = 1; i <= 10; i++) {              basket.pop(id);              try {                  Thread.sleep(2000);              } catch (InterruptedException e) {                  // TODO Auto-generated catch block                  e.printStackTrace();              }          }        }    }public class Test {      public static void main(String[] args) {          Basket basket = new Basket();          // 两个厨师两个客户          Kitchener kitchener1 = new Kitchener(1,basket);          Kitchener kitchener2 = new Kitchener(2,basket);          Customer customer1 = new Customer(1,basket);          Customer customer2 = new Customer(2,basket);          new Thread(kitchener1).start();          new Thread(kitchener2).start();          new Thread(customer1).start();          new Thread(customer2).start();      }    } 

名字和年龄对应错误了,

http://www.cnblogs.com/rollenholt/archive/2011/08/28/2156357.html

更多相关文章

  1. Android(安卓)AsyncTask
  2. Android(安卓)UI主进程跟子进程直接相互通信
  3. Android(安卓)判断当前线程是否是UI主线程
  4. Android的线程和线程池
  5. Android音频系统之音量控制详解(Android(安卓)5.1)
  6. Android(安卓)AsyncTask异步线程
  7. Android的线程和线程池
  8. Android(安卓)线程
  9. 解析Android的 消息传递机制Handler

随机推荐

  1. TabWidget/TabHost的两种使用方法
  2. Android(安卓)Studio中的build.gradle文
  3. Android中menu详解
  4. Android(安卓)近百个项目的源代码,覆盖And
  5. android selector下的设置背景属性值
  6. android布局
  7. Android之硬键盘字符映射------KeyCharac
  8. APK中实现关机
  9. android ramdisk
  10. Android中am命令用法详解