Chinaunix首页 | 论坛 | 博客
  • 博客访问: 134963
  • 博文数量: 34
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 700
  • 用 户 组: 普通用户
  • 注册时间: 2014-11-12 16:52
文章分类

全部博文(34)

文章存档

2015年(13)

2014年(21)

我的朋友

分类: Java

2014-12-10 14:36:15

多线程的两种创建方式:

下面这些东西是API文档中的:



public class Thread

extends Object

implements Runnable

线程 是程序中的执行线程。Java 虚拟机允许应用程序并发地运行多个执行线程。 

每个线程都有一个优先级,高优先级线程的执行优先于低优先级线程。每个线程都可以或不可以标记为一个守护程序。当某个线程中运行的代码创建一个新 Thread 对象时,该新线程的初始优先级被设定为创建线程的优先级,并且当且仅当创建线程是守护线程时,新线程才是守护程序。 

当 Java 虚拟机启动时,通常都会有单个非守护线程(它通常会调用某个指定类的 main 方法)。Java 虚拟机会继续执行线程,直到下列任一情况出现时为止: 

· 调用了 Runtime 类的 exit 方法,并且安全管理器允许退出操作发生。 

· 非守护线程的所有线程都已停止运行,无论是通过从对 run 方法的调用中返回,还是通过抛出一个传播到 run 方法之外的异常。 

创建新执行线程有两种方法。一种方法是将类声明为 Thread 的子类。该子类应重写 Thread 类的 run 方法。接下来可以分配并启动该子类的实例。例如,计算大于某一规定值的质数的线程可以写成: 



  1. class PrimeThread extends Thread  
  2. {  
  3.     long minPrime;  
  4.     PrimeThread(long minPrime)  
  5.     {  
  6.         this.minPrime = minPrime;  
  7.     }  
  8.   
  9.     public void run()  
  10.     {  
  11.         // compute primes larger than minPrime  
  12.         . . .  
  13.     }  
  14. }  



 

然后,下列代码会创建并启动一个线程: 

    

  1. PrimeThread p = new PrimeThread(143);  
  2. p.start();  


创建线程的另一种方法是声明实现 Runnable 接口的类。该类然后实现 run 方法。然后可以分配该类的实例,在创建 Thread 时作为一个参数来传递并启动。采用这种风格的同一个例子如下所示: 

 

  1. class PrimeRun implements Runnable  
  2. {  
  3.     long minPrime;  
  4.     PrimeRun(long minPrime)  
  5.     {  
  6.         this.minPrime = minPrime;  
  7.     }  
  8.   
  9.     public void run()  
  10.     {  
  11.         // compute primes larger than minPrime  
  12.         . . .  
  13.     }  
  14. }  



 

然后,下列代码会创建并启动一个线程: 

     

  1. PrimeRun p = new PrimeRun(143);  
  2. new Thread(p).start();  


每个线程都有一个标识名,多个线程可以同名。如果线程创建时没有指定标识名,就会为其生成一个新名称。

---------------------------------------------

线程的创建方式:

1.继承Thread

2.实现Runnable

 

第一种方式:继承Thread类

实现步骤:

1.自定义类继承Thread

2.复习Thread中的run()方法

3.创建该类的对象,调用start()方法,开启线程并调用run方法

 

简单实现:


  1. class MyThread extends Thread  
  2. {  
  3.     public void run ()  
  4.     {  
  5.         for (int i = 0; i < 100; i++)  
  6.         {  
  7.             System.out.println("MyThread.run()..."+i);  
  8.         }  
  9.     }  
  10. }  
  11. public class THREAD  
  12. {  
  13.     public static void main (String[] args)  
  14.     {  
  15.         MyThread a = new MyThread();  
  16.         a.start();  
  17.         for (int j = 0; j < 100; j++)  
  18.         {  
  19.             System.out.println("THREAD.main()----"+j);  
  20.         }  
  21.     }  
  22. }  



多运行几次会发现:

i所在的线程和j所在的线程会交替运行

但是每次运行的结果却是不一样的

这就是多线程的随机性

 

为什么要覆盖run方法?

Thread 用于描述线程,该类就定义了一个功能,用于存储线程要运行的代码

该存储功能就是run方法。

 

第二种创建方式:实现Runnable

Runnable是一个简单的接口,该接口中只有一个抽象方法:run方法。

实现步骤:

1.定义一个实现Runnable接口的类

2.覆盖run方法

3.创建该类对象,并以该类对象为参数创建Thread类的对象,从而创建了一个线程

4.调用start方法,开启线程并调用run方法。

 

简单创建:


  1. class MyThread implements Runnable  
  2. {  
  3.     public void run ()  
  4.     {  
  5.         for (int i = 0; i < 50; i++)  
  6.         {  
  7.             System.out.println("MyThread.run()..."+i);  
  8.         }  
  9.     }  
  10. }  
  11. public class THREAD  
  12. {  
  13.     public static void main (String[] args)  
  14.     {  
  15.         MyThread a = new MyThread();  
  16.         Thread a1 = new Thread(a);  
  17.         Thread a2 = new Thread(a);  
  18.         Thread a3 = new Thread(a);  
  19.         Thread a4 = new Thread(a);  
  20.   
  21.         a1.start();  
  22.         a2.start();  
  23.         a3.start();  
  24.         a4.start();  
  25.     }  
  26. }  



该例子中创建了四个线程,能够实现四个线程的交替运行,但是却看不出是哪个线程执行的,

调用Thread类中的getName方法可以解决这个问题


  1. System.out.println(Thread.currentThread().getName()+"..."+i);  

currentThread():获取当前线程对象

线程的名字 

Thread-0

Thread-1

...

线程都有自己默认的名称,Thread-编号  编号从0开始

也可以自己定义线程的名称。


  1. class MyThread implements Runnable  
  2. {  
  3.     private String name;  
  4.     public MyThread(String name)  
  5.     {  
  6.         this.name = name;  
  7.     }  
  8.   
  9.     public String GetName()  
  10.     {  
  11.         return name;  
  12.     }  
  13.     public void run ()  
  14.     {  
  15.         for (int i = 0; i < 50; i++)  
  16.         {  
  17.             System.out.println(this.GetName()+"..."+i);  
  18.         }  
  19.     }  
  20. }  
  21. public class THREAD  
  22. {  
  23.     public static void main (String[] args)  
  24.     {  
  25.         MyThread a = new MyThread("My");  
  26.         MyThread b = new MyThread("Your");  
  27.         Thread a1 = new Thread(a);  
  28.         Thread a2 = new Thread(b);  
  29.   
  30.         a1.start();  
  31.         a2.start();  
  32.   
  33.     }  
  34. }  



如果用的是 继承Thread类的方式 直接用super就可以,

因为Thread类中有getName这个方法,通过构造函数初始化线程,然后直接调用getName方法就行。


  1. class MyThread extends Thread  
  2. {  
  3.     private String name;  
  4.     public MyThread(String name)  
  5.     {  
  6.         super(name);  
  7.     }  
  8.   
  9. //  public String GetName(){  
  10. //      return name;  
  11. //  }  
  12.     public void run ()  
  13.     {  
  14.         for (int i = 0; i < 50; i++)  
  15.         {  
  16.             System.out.println(Thread.currentThread().getName()+"..."+i);  
  17.         }  
  18.     }  
  19. }  
  20. public class THREAD  
  21. {  
  22.     public static void main (String[] args)  
  23.     {  
  24.         MyThread a = new MyThread("My");  
  25.         MyThread b = new MyThread("Your");  
  26. //      Thread a1 = new Thread(a);  
  27. //      Thread a2 = new Thread(b);  
  28.   
  29.         a.start();  
  30.         b.start();  
  31.   
  32.     }  
  33. }  





两种方式的区别:

第一种:继承Thread的方法:

1.缺点:Java语言只允许单继承,所以该类继承了Thread之后就不可以再继承其他的类了

2.优点:编写简单。

第二种:实现Runnable接口的方式:

1.缺点:编写稍显复杂

2.优点:

a) 避免由于单继承带来的局限性

b) 有利于代码的健壮性,代码能够被多个线程共享,代码与数据是独立的

代码存放的位置:

继承Thread方式:线程代码存放于Thread子类的run方法中

实现Runnable方式:线程代码存放于接口子类的run方法中。

更多精彩内容请浏览
阅读(803) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~