Java编程思想 之 线程简单应用
来源:互联网 发布:个人顶级域名 编辑:程序博客网 时间:2024/05/21 06:54
1.基本线程机制
并发编程使我们可以将程序划分为多个分离的,独立运行的任务。通过使用多线程机制,这些独立任务中的每一个都将由执行线程来驱动。一个线程就是在进程中的一个单一的顺序控制流,因此,单个进程可以拥有多个并发执行的任务。
2.Java中如何编写多线程
2.1 定义任务
下面的LiftOff任务监视发射之前的倒计时:
public class LiftOff implements Runnable { protected int countDown = 10; // 默认从10开始倒计时 private static int taskCount = 0;//总线程的个数 private final int id = taskCount++;//线程的ID public LiftOff() {} public LiftOff(int countDown) { this.countDown = countDown; } //显示当前线程ID和倒计时数 public String status() { return "#" + id + "(" + (countDown > 0 ? countDown : "Liftoff!") + "), "; } public void run() { while(countDown-- > 0) { System.out.print(status()); Thread.yield(); } }}
其中的Thread.yield()的调用是对线程调度器的一种建议。它在声明:”我已经完成了任务,此刻是切换给其他任务一段时间的大好时机.”
2.2 Thread类
Thread构造器只需要一个Runnable对象.
public class BasicThreads { public static void main(String[] args) { Thread t = new Thread(new LiftOff()); t.start(); System.out.println("Waiting for LiftOff"); }}
//outputWaiting for LiftOff#0(9), #0(8), #0(7), #0(6), #0(5), #0(4), #0(3), #0(2), #0(1), #0(Liftoff!),
这里main方法本身就是一个线程,当在创建一个线程的时候,程序会同时运行两个方法,main()和LiftOff.run().
2.3 Executor
JavaSE5的java.util.concurrent中的执行器(Executor)将为你管理Thread对象,从而简化并发编程.Executor是启动任务的优选方法.
public class CachedThreadPool { public static void main(String[] args) { //创建缓存线程池 ExecutorService exec = Executors.newCachedThreadPool(); for(int i = 0; i < 5; i++) //将任务加入到Executor管理 exec.execute(new LiftOff()); exec.shutdown(); }}
//output#4(9), #4(8), #4(7), #4(6), #3(9), #3(8), #1(9), #2(9), #0(9), #0(8), #2(8), #1(8), #3(7), #4(5), #3(6), #1(7), #2(7), #0(7), #2(6), #1(6), #3(5), #4(4), #3(4), #1(5), #2(5), #0(6), #2(4), #1(4), #3(3), #4(3), #4(2), #4(1), #3(2), #4(Liftoff!), #1(3), #1(2), #1(1), #1(Liftoff!), #2(3), #0(5), #2(2), #3(1), #2(1), #0(4), #2(Liftoff!), #3(Liftoff!), #0(3), #0(2), #0(1), #0(Liftoff!),
在这里使用的CachedThreadPool在程序执行过程中通常会创建于所需数量相同的线程,然后在它回收旧线程时停止创建新线程,因此它是Executor的首选.
除了CachedThreadPool,还有FixedThreadPool(一次性执行代价高昂的线程分配)和SingleThreadExecutor(所有任务将使用相同线程).
2.4 任务中返回值
实现Callable接口
class TaskWithResult implements Callable<String> { private int id; public TaskWithResult(int id) { this.id = id; } public String call() { return "result of TaskWithResult " + id; }}public class CallableDemo { public static void main(String[] args) { ExecutorService exec = Executors.newCachedThreadPool(); //记录线程的返回Future对象 ArrayList<Future<String>> results = new ArrayList<Future<String>>(); for(int i = 0; i < 10; i++) results.add(exec.submit(new TaskWithResult(i))); for(Future<String> fs : results) try { // 得到返回值 System.out.println(fs.get()); } catch(InterruptedException e) { System.out.println(e); return; } catch(ExecutionException e) { System.out.println(e); } finally { exec.shutdown(); } }}
//outputresult of TaskWithResult 0result of TaskWithResult 1result of TaskWithResult 2result of TaskWithResult 3result of TaskWithResult 4result of TaskWithResult 5result of TaskWithResult 6result of TaskWithResult 7result of TaskWithResult 8result of TaskWithResult 9
如果Future任务没有完成,get()方法将堵塞. exec.shutdown()方法的调用可以防止新任务被提交给这个Executor.
2.5 优先级
public class SimplePriorities implements Runnable { //倒计时值 private int countDown = 5; //原子性的double类型 private volatile double d; // No optimization //优先级 private int priority; public SimplePriorities(int priority) { this.priority = priority; } //输出当前线程+递减值 public String toString() { return Thread.currentThread() + ": " + countDown; } public void run() { //设置优先级 Thread.currentThread().setPriority(priority); while(true) { // 执行耗时操作 for(int i = 1; i < 100000; i++) { d += (Math.PI + Math.E) / (double)i; if(i % 1000 == 0) Thread.yield(); } //输出 System.out.println(this); if(--countDown == 0) return; } } public static void main(String[] args) { ExecutorService exec = Executors.newCachedThreadPool(); for(int i = 0; i < 5; i++) exec.execute( //设置最低优先级 new SimplePriorities(Thread.MIN_PRIORITY)); exec.execute( //设置最高优先级 new SimplePriorities(Thread.MAX_PRIORITY)); exec.shutdown(); }}
//outputThread[pool-1-thread-3,1,main]: 5Thread[pool-1-thread-6,10,main]: 5Thread[pool-1-thread-2,1,main]: 5Thread[pool-1-thread-3,1,main]: 4Thread[pool-1-thread-1,1,main]: 5Thread[pool-1-thread-4,1,main]: 5Thread[pool-1-thread-5,1,main]: 5Thread[pool-1-thread-6,10,main]: 4Thread[pool-1-thread-3,1,main]: 3Thread[pool-1-thread-6,10,main]: 3Thread[pool-1-thread-2,1,main]: 4Thread[pool-1-thread-3,1,main]: 2Thread[pool-1-thread-1,1,main]: 4Thread[pool-1-thread-6,10,main]: 2Thread[pool-1-thread-5,1,main]: 4Thread[pool-1-thread-4,1,main]: 4Thread[pool-1-thread-3,1,main]: 1Thread[pool-1-thread-6,10,main]: 1Thread[pool-1-thread-2,1,main]: 3Thread[pool-1-thread-4,1,main]: 3Thread[pool-1-thread-5,1,main]: 3Thread[pool-1-thread-1,1,main]: 3......
pool-1-thread-6为高优先级线程.
在这里可以看出,就算设置了高的优先级,也只是使最高优先级被选择的概率增高,并不会只先执行优先级高的线程.
2.6 后台线程
public class SimpleDaemons implements Runnable { public void run() { try { while(true) { //线程睡眠 TimeUnit.MILLISECONDS.sleep(100); System.out.println(Thread.currentThread() + " " + this); } } catch(InterruptedException e) { System.out.println("sleep() interrupted"); } } public static void main(String[] args) throws Exception { for(int i = 0; i < 10; i++) { Thread daemon = new Thread(new SimpleDaemons()); //设置为后台线程,该方法必须在start()执行 daemon.setDaemon(true); // Must call before start() daemon.start(); } System.out.println("All daemons started"); TimeUnit.MILLISECONDS.sleep(175); }}
//outputAll daemons startedThread[Thread-1,5,main] com.praysz.thread.SimpleDaemons@126be4ccThread[Thread-8,5,main] com.praysz.thread.SimpleDaemons@4e5ced83Thread[Thread-7,5,main] com.praysz.thread.SimpleDaemons@36ed5ba6Thread[Thread-2,5,main] com.praysz.thread.SimpleDaemons@697a1686Thread[Thread-4,5,main] com.praysz.thread.SimpleDaemons@697a1686Thread[Thread-0,5,main] com.praysz.thread.SimpleDaemons@126be4ccThread[Thread-6,5,main] ......
JavaSE5引入了更加显示的sleep版本,作为TimeUnit类的一部分.
当把main方法中的最后TimeUnit.MILLISECONDS.sleep(175)去除后
//outputAll daemons started
这说明,当最后一个非后台线程终止时,后台线程会”突然终止”,因此一旦main()方法退出,JVM会立即关闭所有的后台进程.
- Java编程思想 之 线程简单应用
- Java编程思想 之 线程协作
- java简单编程思想
- Java编程思想之多线程
- java编程思想笔记-并发之线程加入
- java编程思想-并发之线程异常处理器
- java编程思想笔记-并发之线程协作(一)
- java编程思想笔记-并发之线程协作(二)
- java编程思想笔记-并发之线程协作(三)
- java编程思想笔记-并发之线程协作(四)
- Java编程思想之15.2简单泛型
- java编程思想之泛型类
- Java编程思想之并发
- Java编程思想之复用类
- Java编程思想之接口
- Java编程思想之字符串
- Java编程思想之字符串
- Java编程思想之数组
- maven(二) 使用maven
- css 样式表
- 解决cookie过大问题
- jQuery使用prop设置checkbox全选、反选
- jQuery is not must for us--元素选取
- Java编程思想 之 线程简单应用
- 【手游】有杀气童话 美术资源加密分析
- 自定义checkbox
- Linux环境下为Tomcat安装APR
- 全面认识ldap
- MyEclipse配置Tomcat
- C语言编写小游戏——骑士飞行棋
- Android Studio 手动完成项目配置
- 14.9.3 InnoDB Checkpoints InnoDB 检查点