《JAVA多线程》

来源:互联网 发布:程序员年纪大了怎么办 编辑:程序博客网 时间:2024/05/22 16:58

一.   run()与start()的区别

1.   对象.run()是用对象调用run()方法,而对象.start()是将run()作为线程方法,进行调用。

2.    

对象A.run();

对象B.run();

是执行完A所有的run()方法再执行B的run()方法。


对象A.start();

对象B.start();

是A与B的run()方法同步执行,A先执行一次再到B执行一次。


二.多线程的优点

1.   加快程序的运行速度;

2.   使用GUI界面设计,利用事件处理和GUI可以弹出进度条显示处理的进度等

3.   在一些等待的任务的实现上可以使用线程。如用户输入、文件读写和网络收发数据等,在这种情况下我们可以释放一些资源,如内存占用、CPU占用等。


三.     创建线程的方式(重点)

线程的创建方式有两种,继承Thread类和实现Runnable接口

1.   继承Thread类

//例14.3 该程序分别打印线程A、线程B、线程C各3次

public class MultiThreadExample1 {

     public static void main(Stringargs[]) {

         MyThread1 t1 =new MyThread1("A");// 创建线程对象t1,①

         MyThread1 t2 = newMyThread1("B");

         MyThread1 t3 = newMyThread1("C");

         t1.start();// 启动线程t1

         t2.start();

         t3.start();

     }

}

 

class MyThread1 extends Thread {// 定义线程类MyThread1,必须继承类Thread

     String name;

 

     public MyThread1(String n) {

         name = n;

     }   

     public void run(){// 线程执行主体,

         for (int i = 0; i < 3;i++) {

              try {

                   Thread.sleep((long)Math.random() * 1000);

              } catch(InterruptedException e) {

                   e.printStackTrace();

              }

              System.out.println("访问:" + name);

         }

       }

}

①start()方法首先要进行必要的初始化,如设定线程运行状态,然后才能调用run()方法启动线程,所以不调用start()而直接调用run()方法是无法启动线程的。

②注意Thread类创建本身的run()是空的,子类继承必须覆盖run()方法

 

2.实现Runnable接口创建线程

//例14.4 该程序分别打印线程A、线程B、线程C各3次

public class MultiThreadExample2 {

     public static void main(Stringargs[]) {

         // 将MyThread2的对象作为Thread类的构造方法的参数,创建线程对象

         Thread t1 = newThread(new MyThread2("A"));

//或者  Runnable a=new MyThread2("A");

              Threadt1=new Thread(a);

         Thread t2 = new Thread(newMyThread2("B"));

         Thread t3 = new Thread(newMyThread2("C"));

         t1.start();// 启动线程t1

         t2.start();

         t3.start();

     }

}

 

class MyThread2 implements Runnable {

// 定义线程类MyThread2,实现Runnable接口

     String name;

     public MyThread2(String n) {

         name = n;

     }   

     public void run(){// 线程执行主体

         for (int i = 0; i < 3;i++) {

              try {

                   Thread.sleep((long)Math.random() * 1000);

              } catch(InterruptedException e) {

                   e.printStackTrace();

              }

              System.out.println("访问:" + name);

         }

     }

}

 

3.两种创建线程方式的比较

(1)从继承方面,Java不支持多重继承,一个继承了Thread的类将无法再继承其他类,因此在某些情况只能采用实现Runnbale接口的方式。

(2)从调用语句方面,Thread可以直接调用当前线程自身的方法,而实现Runnable接口的方法需要形如Runnable a=new MyThread2("A");Thread t1=new Thread(a);较麻烦。

(3)如要获取拥有特殊功能的线程必须通过继承并扩充Thread接口实现或对Thread类的修改或扩充不大,更应采用继承Thread类的方式。

 

4.多线程的生命周期

常用的Thread对象方法:

String getNmae()//获取线程名

static Thread currentThread()//返回当前线程

void destroy()//销毁线程

 

5.线程间的协作

synchronized()方法:用其控制对类成员变量的访问,每个设置了synchronized 的方法一旦被执行,就独占该锁,知道该方法返回才将锁释放,才轮到下一个线程执行。

典型举例(生产者与消费者的问题):

//实例14.7 Box对象用来存放数据

public class Box {

         privateint value;

         //是否可以使用,true可读取数据,false可写入数据

         privateboolean available = false;

         publicvoid put(int value) {

              while(available == true) {

                   try{

                       wait();//等待,提供给其他线程使用

                   }catch(InterruptedException e) {

                       e.printStackTrace();

              }

         }

         available= true;// 表示可读取数据

         notifyAll();//唤醒所有等待线程

         this.value= value;// 写入数据

     }

     publicint get() {

         while(available == false) {

              try{

                   wait();

              }catch (InterruptedException e) {

                   e.printStackTrace();

              }

         }

         available= false;// 表示可写入数据

         notifyAll();//唤醒所有等待线程

         returnthis.value;// 读取数据

     }

}

 

public class 生产者 extends Thread {//生产者对象产生数据

     privateBox box;

     privateString name;

     public生产者(Box b, String n) {

         box= b;

         name= n;

     }

     publicvoid run() {

         for(int i = 1; i < 6; i++) {

              synchronized (box) {//Java线程通过锁定一个对象来达到分别对box对象进行操作的目的

                   box.put(i);//存放数据i入box对象

                   System.out.println("生产者" + name + "生产产品:" + i);

                   try{

                       sleep((int)(Math.random() * 100));

                   }catch (InterruptedException e) {

                       e.printStackTrace();

                   }

              }

         }

     }

}

public class 消费者 extends Thread {//消费者对象获取数据

     privateBox box;

     privateString name;

     public消费者(Box b, String n) {

         box= b;

         name= n;

     }

     publicvoid run() {

         for(int i = 1; i < 6; i++) {

              synchronized (box){

                   box.get();//从box对象中取出数据i

                   System.out.println("消费者" + name + "取得产品:" + i);

                   try{

                       sleep((int)(Math.random() * 100));

                   }catch (InterruptedException e) {

                       e.printStackTrace();

                   }

              }

         }

     }

}

public class 生产者消费者测试 {//主类

     publicstatic void main(String args[]) {

         Boxbox = new Box();

         生产者 p = new 生产者(box, "001");// 创建生产者001,往box对象中存数据

         消费者 c = new 消费者(box, "002");// 创建消费者002,从box对象中取数据

         p.start();

         c.start();

     }

}

注意:若不注意使用协作,会出现两个对象分别不按先后执行相关方法,导致处于资源竞争的状态。

0 0
原创粉丝点击