JAVA学习笔记 -- 线程

34 篇文章 0 订阅

之前学习的都是关于顺序编程的知识,程序在任意时刻都只能执行一个步骤。线程作为我接触并发编程的第一堂课,我感觉很兴奋。

1、定义任务

   实现Runnable接口并编写run()方法(线程将会执行此方法内代码)。

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. class LiftOff implements Runnable {    
  2.     protected int countDown = 10;  
  3.     private static int taskCount = 0;  
  4.     private final int id = taskCount++;  
  5.       
  6.     public LiftOff() {  
  7.     }  
  8.     public LiftOff(int countDown) {  
  9.         this.countDown = countDown;  
  10.     }  
  11.     public String status() {  
  12.         return "#" + id + "("  
  13.                 + (countDown > 0 ? String.valueOf(countDown) : "Liftoff!")  
  14.                 + "),";  
  15.     }  
  16.     public void run() {  
  17.         while (countDown-- > 0) {  
  18.             System.out.print(status());  
  19.             Thread.yield();  
  20.         }  
  21.         System.out.println();  
  22.     }  
  23. }  
  24.   
  25. public class ThreadTest {  
  26.     public static void main(String[] args) {  
  27.         LiftOff launch = new LiftOff();  
  28.         launch.run();  
  29.     }  
  30. }/* 
  31.  * Output: #0(9),#0(8),#0(7),#0(6),#0(5),#0(4),#0(3),#0(2),#0(1),#0(Liftoff!), 
  32.  */// :~  
如上代码,从Runnable导出一个类,再调用它的run()方法,但这个方法不会产生任何内在的线程能力。

要实现线程行为,必须将它附着到线程上。


2、创建和启动线程

A. 通过Thread构造器。将Runnable对象提交给一个Thread构造器,再调用Thread对象的start()方法启动线程。

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. public class ThreadTest {  
  2.     public static void main(String[] args) {  
  3.         Thread t = new Thread(new LiftOff());  
  4.         t.start();  
  5.         System.out.println("Waiting for LiftOff");  
  6.     }  
  7. }/* 
  8.  * Output: Waiting for LiftOff 
  9.  * #0(9),#0(8),#0(7),#0(6),#0(5),#0(4),#0(3),#0(2),#0(1),#0(Liftoff!), 
  10.  */// :~  
在main()线程中,start()迅速的返回,此时子线程t执行的LiftOff.run()任务还未结束。这时两个线程并发运行,通过输出也可以看出。


B. 使用Executor。Executor是java.util.concurrent包中的执行器,可以更好的管理Thread对象。

a. CachedThreadPool,为每个任务都创建一个线程。

b. FixedThreadPool,使用有限的线程集来执行所提交的任务。

c. SingeThreadExecutor,如线程数量为1的FixedThreadPool。

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. public class ThreadTest {  
  2.     public static void main(String[] args) {  
  3.         ExecutorService exec1 = Executors.newCachedThreadPool();  
  4.         ExecutorService exec2 = Executors.newFixedThreadPool(5);//线程集限制数目为5  
  5.         ExecutorService exec3 = Executors.newSingleThreadExecutor();  
  6.         exec1.execute(new LiftOff());  
  7.         exec1.shutdown();//防止新任务被提交给这个Executors  
  8.     }  
  9. }  

3、Callable接口

Runnable是执行工作的独立任务,但它没有返回值。而Callable可以从任务中产生返回值。

下面代码展示它的用法:

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. import java.util.concurrent.*;  
  2. import java.util.*;  
  3. class TaskWithResult implements Callable<String> {  
  4.     private int id;  
  5.   
  6.     public TaskWithResult(int id) {  
  7.         this.id = id;  
  8.     }  
  9.     public String call() {  
  10.         return "result of TaskWithResult " + id;  
  11.     }  
  12. }  
  13.   
  14. public class ThreadTest {  
  15.     public static void main(String[] args) {  
  16.         ExecutorService exec = Executors.newCachedThreadPool();  
  17.         ArrayList<Future<String>> results = new ArrayList<Future<String>>();  
  18.         for (int i = 0; i < 10; i++) {  
  19.             results.add(exec.submit(new TaskWithResult(i)));  
  20.             // Callable的调用方式必须是 ExecutorService.submit(),  
  21.             // 同时submit()会产生一个Future对象,可以通过isDone()查询Future是否完成,通过get()获取call()的返回值.  
  22.         }  
  23.         for (Future<String> fs : results)  
  24.             try {  
  25.                 System.out.print(fs.get() + ",");  
  26.             } catch (InterruptedException e) {  
  27.                 System.out.println(e);  
  28.                 return;  
  29.             } catch (ExecutionException e) {  
  30.                 System.out.println(e);  
  31.             } finally {  
  32.                 exec.shutdown();  
  33.             }  
  34.     }  
  35. }/* 
  36.  * Output: result of TaskWithResult 0,result of TaskWithResult 1,result of 
  37.  * TaskWithResult 2,result of TaskWithResult 3,result of TaskWithResult 4,result 
  38.  * of TaskWithResult 5,result of TaskWithResult 6,result of TaskWithResult 
  39.  * 7,result of TaskWithResult 8,result of TaskWithResult 9, 
  40.  */// :~  


4、线程相关方法和知识

a. yield(),表示当前线程已经完成或暂时不需要CPU,其它线程可以占用之,这只是个建议。

b. 优先级,通过getPriority()和setPriority()方法获取和重置线程的优先级,优先级和多数操作系统都不能映射的很好,唯一可移植的是设置优先级时,只使用 MAX_PRIORITY、NORM_PRIORITY和MIN_PRIORITY三个级别。

c. deamon(后台线程),它是程序运行的时候在后台提供的一种通用服务的线程,当所有非后台线程结束时,程序会杀死所有后台线程。

设置成后台线程的方法是:必须在线程启动前调用 setDaemon(true),后台线程派生出来的子线程都是后台线程。

d. join(),如果某个线程在另一个线程t上调用t.join(),此线程会被挂起,直到目标线程t结束才可恢复(即t.isAlive()返回为false)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值