您的位置:首页 > 职场人生

黑马程序员-多线程

2012-11-25 22:37 357 查看
------- android培训java培训、期待与您交流! ----------

Thread.currentThread().getName()方法得到当前程序执行线程的名字

 

创建线程第一种方法:让实现线程类继承Thread类,然后重写run()方法(被继承的Thread的run()方法没有方法体,主要用于执行内容),在主函数中新建出实现线程的类并调用start()方法,就会自动执行run()中的内容

public
class
ThreadDemo {
 
    /**
     * @param args
     */
    public
static void
main(String[] args) {
       //在主函数调用新建的实现线程的类并start
       new ThreadTest().start();
       while(true){
           System.out.println("main()" + Thread.currentThread().getName());
       }
    }
}
    //让线程继承Thread类并复写run方法
    class ThreadTest
extends Thread{
 
       @Override
       public
void
run() {
           // TODO Auto-generatedmethod stub
           while(true){
              System.out.println("run()" + Thread.currentThread().getName());
           }
       }
      
    }

 

后台线程与联合线程:

后台线程TestThread t = new TestThread();
       t.setDaemon(true);//设为后台线程

当没有前台线程运行时,后台线程也随之结束

联合线程线程用join()方法联合,并自动成为当前线程的子线程,先执行完子线程在执行主线程。

注意:join(参数)中的参数是时间,当两个线程合并指定时间后再分为两个不同线程

public
class
ThreadDemo {
 
    /**
     * @param args
     */
    public
static void
main(String[] args) {
       //在主函数调用新建的实现线程的类并start
       Thread t = new ThreadTest();
       t.start();
       int index = 0;
       while(true){
           if(index++ == 50000)
              try {
                  t.join();
              } catch (InterruptedException e) {
                  // TODO Auto-generatedcatch block
                  e.printStackTrace();
              }
           System.out.println("main()" + Thread.currentThread().getName());
       }
    }
}
    //让线程继承Thread类并复写run方法
    class ThreadTest
extends Thread{
 
       @Override
       public
void
run() {
           // TODO Auto-generatedmethod stub
           while(true){
              System.out.println("run()" + Thread.currentThread().getName());
           }
       }
      
    }

创建线程的第二种方法:创建出thread类,并将继承过Runnable的类当做参数传入,与第一种方法一样,覆写run()方法

class TestThread implements Runnable{

public
void
run(){

}

}

Thread t = new Thread(new TestThread());

 

创建线程两种方法的区别:

继承runnable更适合操作同一资源

 

 

使用Runnable接口创建多线程

1.      适合多个相同程序代码的线程去处理同一资源的情况,把虚拟CPU(线程)同程序的代码、数据有效分离,较好的体现了面向对象的设计思想

2.      可以避免由于Java的单继承特性带来的局限。我们经常碰
4000
到这样一种情况,即当我们要将已经继承了某一个类的子类放入多线程中,由于一个类不能同时有两个父类,所以不能继承Thread类的方式,那么,这个类就只能采用实现Runnable

3.      当线程被构造时,需要的代码和数据通过一个对象作为构造函数实参传递进去,这个对象就是一个实现了Runnable接口的类的实例

4.      事实上,几乎所有多线程应用都可用Runnable接口方式

创建多线程的用处:

例子:

1.      网络聊天程序的收发

a)        没有线程的



b)       多线程的



2.      表记录的复制和中途取消

3.      www服务器为一个来访者都建立专线服务

 

有关线程安全性问题:

以售票为例:当还剩最后一张票时,四个售票口可能同时出售…

所以,在线程类中,只能有像独木桥只允许一个线程通过,用synchronized()实现

用synchronized(){}的形式括起来

Synchronized会加大内存的开销,如果确定没有安全性问题就可以不加

注意:要将string放在run()方法的外部

class TestThread
implements Runnable/*extendsThread*/{
    //然后重写run()方法
    int
tickets = 1000;
    String str = new String("");
    public
void
run(){
       if(str.equals("method")){
           while(true){
              sale();
           }
       }else{
       while(true){
           synchronized(str){
              if(tickets > 0){
                  try {
                     Thread.sleep(10);
                  } catch (InterruptedException e) {
                     // TODO Auto-generatedcatch block
                     e.printStackTrace();
                  }
                  synchronized (this) {}
              System.out.print("代码:");
              System.out.println("run():"+Thread.currentThread().getName()+"is salling ticket"+tickets--);
                  }
           }
       }
       }
 
    }
}

 

想让代码块与方法同步,必须让代码块中的synchronized参数为this

死锁问题:应尽量使用同一个参数,以避免死锁的发生

class TestThread
implements Runnable/*extendsThread*/{
    //然后重写run()方法
    int
tickets = 1000;
    String str = new String("");
    public
void
run(){
       if(str.equals("method")){
           while(true){
              sale();
           }
       }else{
       while(true){
           synchronized(str){
              if(tickets > 0){
                  try {
                     Thread.sleep(10);
                  } catch (InterruptedException e) {
                     // TODO Auto-generatedcatch block
                     e.printStackTrace();
                  }
                  synchronized (this) {}
              System.out.print("代码:");
              System.out.println("run():"+Thread.currentThread().getName()+"is salling ticket"+tickets--);
                  }
           }
       }
       }
 
    }
    public
synchronized void
sale(){
       if(tickets > 0){
           try {
              Thread.sleep(10);
           } catch (InterruptedException e) {
              // TODO Auto-generatedcatch block
              e.printStackTrace();
           }
           synchronized (str) {}
           System.out.print("sale():");
           System.out.println("run():"+Thread.currentThread().getName()+"is salling ticket"+tickets--);
           }
    }
}

上例是参数不同导致了死锁…

 

 

 

线程间的通信



1.      wait:告诉当前线程放弃监视器并进入睡眠状态直到其他线程进入同一监视器并调用notify为止

2.      notify:唤醒一个对象监视器中调用wait的第一个线程,用于类似饭馆有一个空位后通知所有等待就餐的顾客的第一个可以入座的情况

3.      notifyAll:唤醒同一对象监视器中调用wait的所有线程,具有最高优先级的线程首先被唤醒并执行。用于类似某个不定期的培训班终于招生满额后,通知学员都来上课的情况



Wait(),notify(),notifyAll()都必须放在sysnchronised中,并且必须用sysnchronised中的参数作为三个方法的对象

 

线程要在同一个类写出,方便其他类调用方法,类中变量用private,方法用共有

 
class Producer
implements Runnable {
    Q q;
    public Producer(Q q){
       this.q = q;
    }
    @Override
    public
void
run() {
       int i = 0;
       while(true){
           /*synchronized(q){
              if(q.bFull == true)
                  try {q.wait();} catch (InterruptedException e1){e1.printStackTrace();}
              if(i == 0){
                  q.name = "张三";
                  try{Thread.sleep(1);}catch(Exception e){}
                  q.sex = "male";
              }else{
                  q.name = "李四";
                  q.sex = "female";
              }
              q.bFull = true;
              q.notify();
           }*/
              if(i == 0)
                  q.put("张三",
"male");
              else
                  q.put("李四",
"female");
              i = (i+1)%2;        
       }
      
 
    }
 
}
class Coneumer
implements Runnable {
    Q q;
    public Coneumer(Q q){
       this.q = q;
    }
    @Override
    public
void
run() {
       while(true){
           /*synchronized(q){
              if(q.bFull == false)
                  try {q.wait();} catch (InterruptedException e){e.printStackTrace();}
              System.out.print(q.name);
              System.out.println(":" + q.sex);
              q.bFull = false;
              q.notify();
           }*/
           q.get();
           }
    }
 
}
class Q{
    private
boolean
bFull = false;
    private String
name = "unknown";
    private String
sex = "unknown";
    public
synchronized void
put(String name,String sex){
       if(bFull)
           try{wait();}catch(Exception e){}
       this.name = name;
       try{Thread.sleep(1);}catch(Exception e){}
       this.sex = sex;
       bFull = true;
       notify();
    }
    public
synchronized void
get(){
       if(!bFull)
           try{wait();}catch(Exception e){}
       System.out.print(name);
       System.out.println(":" +
sex);
       bFull = false;
       notify();
    }
}
public
class
ThreadCommunation{
    public
static void
main(String args[]){
       Q q = new Q();
       new Thread(new Producer(q)).start();
       new Thread(new Coneumer(q)).start();
    }
}

线程生命的控制:



Stop(),suspend(),等方法过时,易导致死锁,不使用
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: