拨开云雾见天日 —— Java多线程编程概念剖析
2017-03-08 16:56
316 查看
说到Java多线程编程,大多数人都会想到继承Thread或实现Runnable编程,new 一个Thread实例,调用start()方法,由OS调用即可。具体过程如下:
这里没考虑安全问题。 可以看到,这里三个线程调度器共同执行一个任务,才能实现线程变量共享:线程调度器A操作改变count值,然后线程调度器B接着操作改变count……以上就是对Java线程编程概念的初步理解……
public class MyThread extends Thread { @Override public void run() { System.out.println("MyThread"); } public static void main(String[] args) { MyThread thread = new MyThread(); thread.start(); System.out.println("运行结束!"); }}继承Thread;
public class MyRunnable implements Runnable { @Override public void run() { System.out.println("MyRunnable"); } public static void main(String[] args) { Thread thread = new Thread(new MyRunnable()); thread.start(); System.out.println("运行结束!"); }}实现Runnable;这里,有一个问题,就是无论继承Thread还是实现Runnable,最后都需要有一个Thread实例,来激活线程。那么,这个实例化的Thread实例是什么呢?仅仅代表一个线程。如果是这样,那么实现了Runnable的对象有代表什么,它与Thread有何不同?让我们来仔细看看Java线程。
Java线程
线程,就是进程中独立运行的子任务。通常理解为轻量级进程,多个线程共享一个进程资源。由于线程是由OS分配与调度,因此容易产生资源竞争问题,所以成为整个多线程开发中的难点。从对线程概念的理解上,可以看到,真正线程应该有两个概念,(线程)任务和(线程)调度。线程任务
再来看看线程代码。无论继承Thread还是实现Runnable,都需要重写一个run()方法,这里面的代码,是线程执行时真正要执行的方法,也就是说,这是线程任务。没任务,线程干嘛?自己玩!!!肯定不可以。从Runnable接口来看,它只有一个声明——run,也就是说,你要为它的实现类指派任务。之所以有Runnable接口,一方面是因为Java是单继承,不可能为了线程继承了Thread还去继承其他类,所以必须要有Runnable。第二,从面向对象设计原则——单一职责来看,一个类只负责某一方面的任务就可以了,避免引入多变量,多变量代表多不确定性,失控的机会会加大。所以需要Runnable的存在,只负责指派线程任务。Thread也是存在run抽象方法的,它本身就是代表线程(具体哪个暂时不说)。由它实例自己然后自己激活也是可以的,要不然,只有一个激活而没有任务,怎么也说不过去。其实Thread也是实现Runnable,自己的任务还参考别人的……public static void main(String[] args) { MyThread thread = new MyThread(); thread.start(); System.out.println("运行结束!"); }这个MyThread继承自Thread类,并(暗藏)重写了run()方法。没任务玩什么!!!
线程调度
有了任务,就要有人执行,就需要有调度。是谁?就是开篇问到的那个问题。两种方式的线程都需要有一个Thread实例,这就是线程调度。对于继承式的线程,我们好理解,自己激活自己的任务,那么对于实现式的线程呢,是怎么激活的?在Thread中,有一个Thread(Runnable target)构造方法,也就是说在Thread里有一个Runnable变量。对此,Thread里是这样注释的:“ What will be run.”。再看看Thread的调度代码:@Override public void run() { if (target != null) { target.run(); }}target就是Runnable实例,也就是先看看有没有单独的任务表(可以把Runnable看做是一个任务表),如果没有,再查看自己的任务。那么,现在就很明显了,Thread类其实更重的职责在于线程调度(虽然也可以指派任务),Runnable是用来指派线程任务。在多线程编程中,有关竞争、安全、同步这种资源处理的问题,都发生在线程任务身上。看看同步关键字synchronized和Thread一点关系都没有。如果不指定锁,那么默认的锁对象就是任务实例。有关状态、优先、通信等,真正涉及到线程本身的运行,这些才是线程调度处理的问题。
线程与共享
为了进一步说明线程任务与线程调度,这里再给出一个常见的线程变量共享例子:public class MyThread extends Thread { private int count = 5; public MyThread(){} /** 设置线程名称 */ public MyThread(String name){ this.setName(name); } @Override public void run() { while(count>0){ count -- ; System.out.println("由 " + this.currentThread().getName() + " 计算,count:= " +count); } } public static void main(String[] args) { MyThread thread = new MyThread(); Thread a = new Thread(thread, "A"); Thread b = new Thread(thread, "B"); Thread c = new Thread(thread, "C"); a.start(); b.start(); c.start(); }}运行结果如下(不同时刻运行结果不一样):
这里没考虑安全问题。 可以看到,这里三个线程调度器共同执行一个任务,才能实现线程变量共享:线程调度器A操作改变count值,然后线程调度器B接着操作改变count……以上就是对Java线程编程概念的初步理解……
相关文章推荐
- JAVA学习笔记--4.多线程编程 part3.JAVA多线程的常见概念和基本类库
- java多线程-概念&创建启动&中断&守护线程&优先级&线程状态(多线程编程之一)
- Java多线程编程总结笔记——二概念与原理
- Java多线程学习-并发编程实践基本概念总结整理
- 【3】Java并发编程:多线程基本概念
- Java多线程编程总结笔记——03概念与原理
- Java多线程编程详解
- Java多线程_编程模型研究
- Java 多线程编程
- 简单直观-实战体会Java多线程编程的精要
- Java多线程编程经验
- JAVA编程思想:第14章 多线程
- java高级多线程编程--关于线程的停止问题
- Java多线程编程经验
- java高级多线程编程--关于线程的停止问题
- Java多线程编程经验
- java高级多线程编程--关于线程的停止问题
- 简单直观-实战体会Java多线程编程的精要 (3)
- Java多线程编程之限制优先级
- java高级多线程编程--关于线程的停止问题