java线程之基础学习总结 

线程实现的两种方式:

java中可以有两种方式实现多线程操作,一种是继承Thread类,另外一种是实现Runnable接口。

继承Thread

Thread类是在java.lang包中定义的

一个类只要继承Thread类,要覆写run()方法。

简单实例

定义MyThread

  1. 定义MyThread类 
  2. public class MyThread extends Thread { 
  3.     private String name; 
  4.     public MyThread(String name) { 
  5.         this.name = name; 
  6.     } 
  7.     public void run() { 
  8.         for (int i = 0; i < 5; i++) { 
  9.             System.out.println(name + "运行:" + i); 
  10.         } 
  11.     } 

编写TestThread类调用: 

  1. public class TestThread { 
  2.     public static void main(String[] args) { 
  3.         MyThread myThread1 = new MyThread("singsong1"); 
  4.         MyThread myThread2 = new MyThread("singsong2"); 
  5.         myThread1.run(); 
  6.         myThread2.run(); 
  7.     } 
  1. 运行结果: 
  2. singsong1运行:0 
  3. singsong1运行:1 
  4. singsong1运行:2 
  5. singsong1运行:3 
  6. singsong1运行:4 
  7. singsong2运行:0 
  8. singsong2运行:1 
  9. singsong2运行:2 
  10. singsong2运行:3 
  11. singsong2运行:4 

从结果可以发现,此时的执行非常的有规律,先执行完第一个对象,再执行第二个对象。

run()方法换成start();一旦调用start()方法,则会通过JVM找到run()方法

Public void start()

使用start()方法启动线程:

  1. public class TestThread { 
  2.     public static void main(String[] args) { 
  3.         MyThread myThread1 = new MyThread("singsong1"); 
  4.         MyThread myThread2 = new MyThread("singsong2"); 
  5.         myThread1.start(); 
  6.         myThread2.start(); 
  7.     } 
  1. 运行结果: 
  2. singsong1运行:0 
  3. singsong1运行:1 
  4. singsong2运行:0 
  5. singsong1运行:2 
  6. singsong2运行:1 
  7. singsong1运行:3 
  8. singsong2运行:2 
  9. singsong1运行:4 
  10. singsong2运行:3 
  11. singsong2运行:4 

从运行结果可以知道,程序时交互式的运行。

因为需要用到CPU的资源,所以每次的运行结果基本是都不一样的

不要调用Thread类或Runnable对象的run方法。直接调用run方法,只会执行同一个线程中的任务,而不会启动新线程。应该调用Thread.start()方法。这个方法将创建一个执行run方法的新线程。


Runnable接口的实现

简单实例

  1. public class RunnableThread implements Runnable { 
  2.     private String name; 
  3.     public RunnableThread(String name) { 
  4.         this.name = name; 
  5.     } 
  6.     public void run() { 
  7.         for (int i = 0; i < 5; i++) { 
  8.             System.out.println(name + "运行:" + i); 
  9.         } 
  10.     } 

编写TestThread1调用 

  1. public class TestThread1 { 
  2.     public static void main(String[] args) { 
  3.          RunnableThread runnableThread1=new RunnableThread("singsong1"); 
  4.          RunnableThread runnableThread2=new RunnableThread("singsong2"); 
  5.         Thread thread1= new Thread(runnableThread1); 
  6.         Thread thread2= new Thread(runnableThread2);      
  7.         thread1.start(); 
  8.         thread2.start();          
  9.     } 
 
  1. 运行结果: 
  2. singsong1运行:0 
  3. singsong1运行:1 
  4. singsong2运行:0 
  5. singsong2运行:1 
  6. singsong2运行:2 
  7. singsong2运行:3 
  8. singsong2运行:4 
  9. singsong1运行:2 
  10. singsong1运行:3 
  11. singsong1运行:4 

Thread类和Runnable接口区别

最大区别是在于资源的共享

如果一个类继承Thread,则资源共享不可共享。而实现Runable接口,能实现资源共享。

例如:

MyThread

  1. public class MyThread extends Thread { 
  2.     private int ticket = 5
  3.     private String name; 
  4.     public MyThread(String name) { 
  5.         this.name = name; 
  6.     } 
  7.     public void run() { 
  8.         for (int i = 0; i < 15; i++) { 
  9.             if (ticket > 0) { 
  10.                 System.out.println(name + "正售出第 " + (ticket--) + "票"); 
  11.             } 
  12.         } 
  13.     } 
  14.  
  15. 调用: 
  16. public class TestThread { 
  17.     public static void main(String[] args) { 
  18.         MyThread myThread1 = new MyThread("singsong1"); 
  19.         MyThread myThread2 = new MyThread("singsong2"); 
  20.         myThread1.start(); 
  21.         myThread2.start(); 
  22.     } 
  23. 运行结果: 
  24. singsong1正售出第 5票 
  25. singsong1正售出第 4票 
  26. singsong1正售出第 3票 
  27. singsong1正售出第 2票 
  28. singsong1正售出第 1票 
  29. singsong2正售出第 5票 
  30. singsong2正售出第 4票 
  31. singsong2正售出第 3票 
  32. singsong2正售出第 2票 
  33. singsong2正售出第 1票 

重复售出了一次

再来看看Runnable接口是怎么实现资源共享的

RunnableThread

  1. public class RunnableThread implements Runnable { 
  2.     private int ticket = 5
  3.     private String name; 
  4.     public RunnableThread(String name) { 
  5.         this.name = name; 
  6.     } 
  7.     public void run() { 
  8.         for (int i = 10; i > 0; i--) { 
  9.             if (ticket > 0) { 
  10.                 System.out.println(name + "正售出第 " + (ticket--) + "票"); 
  11.             } 
  12.         } 
  13.     } 

 编写TestThread1调用:

 
  1. public class TestThread1 { 
  2.     public static void main(String[] args) { 
  3.         RunnableThread runnableThread1 = new RunnableThread("singsong1"); 
  4.         Thread thread1 = new Thread(runnableThread1); 
  5.         Thread thread2 = new Thread(runnableThread1); 
  6.         thread1.start(); 
  7.         thread2.start(); 
  8.     } 
  9. 运行结果: 
  10. singsong1正售出第 5票 
  11. singsong1正售出第 4票 
  12. singsong1正售出第 3票 
  13. singsong1正售出第 2票 
  14. singsong1正售出第 1票 

从运行结果可以得出实现Runnable接口的优点。

大家有没有想过Runnable接口为什么能实现资源的共享,而Thread类不能

 本人个人理解

首先看如下代码: 

  1. public class TestThread1 { 
  2.     public static void main(String[] args) { 
  3.         RunnableThread runnableThread1 = new RunnableThread("singsong1"); 
  4.         RunnableThread runnableThread2 = new RunnableThread("singsong2"); 
  5.         Thread thread1 = new Thread(runnableThread1); 
  6.         Thread thread2 = new Thread(runnableThread2); 
  7.         thread1.start(); 
  8.         thread2.start(); 
  9.     } 

此代码是在TestThread1类的继承上修改的:添加了    RunnableThread runnableThread2 = new RunnableThread("singsong2");

runnableThread1换成runnableThread2

现在我们在运行程序看看结果:

  1. singsong1正售出第 5票 
  2. singsong1正售出第 4票 
  3. singsong1正售出第 3票 
  4. singsong1正售出第 2票 
  5. singsong1正售出第 1票 
  6. singsong2正售出第 5票 
  7. singsong2正售出第 4票 
  8. singsong2正售出第 3票 
  9. singsong2正售出第 2票 
  10. singsong2正售出第 1票 

 

从结果可以知道也重复了一次。

 

总结一下:也是就说Runnable接口能实现资源的共享是因为用同一个实现Runnable接口的子类来创建不同的线程,去执行同一个任务。而Thread却没有这种机制。