张孝祥java.concurrent线程并发学习笔记 - 传统线程回顾
来源:互联网 发布:linux 查看挂起进程 编辑:程序博客网 时间:2024/06/10 03:35
线程的定义:
每个正在系统上运行的程序都是一个进程。每个进程包含一到多个线程。进程也可能是整个程序或者是部分程序的动态执行。线程是一组指令的集合,或者是程序的特殊段,它可以在程序里独立执行。也可以把它理解为代码运行的上下文。所以线程基本上是轻量级的进程,它负责在单个程序里执行多任务。通常由操作系统负责多个线程的调度和执行。
线程的状态:
1、 new 新建
2、 Runnable 可以运行(就绪)
3、 Running 运行(正在运行)
4、 Block 阻塞 挂起
5、 Dead 死亡
线程之间的转换关系:
如何新建并启动线程:
Thread thread = new Thread(){//Thread是线程类,new Thread()即是新建了一个线程。@Overridepublic void run() {//线程当然要运行代码,重写run方法即可加入此线程的运行代码。while(true){try {Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("1:" + Thread.currentThread().getName());System.out.println("2:" + this.getName());}}};thread.start();//启动线程,将线程从新建状态变为可运行状态,将等待CPU调度。Thread thread2 = new Thread(new Runnable(){//新建线程也可以使用Runnable对象,重新Runnable对象的run方法。@Overridepublic void run() {//Thread类的run方法会调用传递的Runnable对象的run方法,所以这里重写Runable对象的run方法。while(true){try {Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("1:" + Thread.currentThread().getName());}}});thread2.start();这两种方式没有什么区别,看个人爱好使用。
推荐第二种方法,因为这更加面向对象,它将线程要运行的代码进行了封装。
如何实现线程的互斥:
线程互斥是指对于共享的资源,在各线程访问时的排它性。当有若干个线程都要使用某一共享资源时,任何时刻最多只允许一个线程去使用,其它要使用该资源的线程必须等待,直到占用资源者释放该资源。
java中的线程互斥使用synchronized关键字,synchronized可以声明一个代码块,可以声明一个方法(可以是静态方法)。
例:
static class Outputer{public void output(String name){int len = name.length();synchronized (Outputer.class) //声明代码块,使用Outputer.class作为锁。{for(int i=0;i<len;i++){System.out.print(name.charAt(i));}System.out.println();}}public synchronized void output2(String name){ //声明方法,将使用this作为锁。int len = name.length();for(int i=0;i<len;i++){System.out.print(name.charAt(i));}System.out.println();}public static synchronized void output3(String name){//声明静态方法,将使用Outputer.class作为锁。int len = name.length();for(int i=0;i<len;i++){System.out.print(name.charAt(i));}System.out.println();}}经验:设计线程互斥代码,需要考虑互斥锁和线程之间的共享数据,设计代码时尽量保证互斥锁、共享数据、synchronized声明归在同一个类的身上,这样既便于维护,同时保证了良好的高内聚,外部调用者不必关心同步控制的问题。
线程协同的通信:
线程互斥本身可以理解为线程通信的一种方式,是一个线程A说“我进去了,等我出来后你们再进”。其它线程就在外面等待,直到看见A出来,其它线程才会进去并且说“我也进去了,等我出来后你们再进”。
但是有这样一种场景,一个线程A在不停的生产面包,放进面包箱里,另一个线程B在不停的从面包箱里取出面包,然后吃掉。当面包箱满的时候,线程A应该暂停,当B吃掉面包时,面包箱变得不满,应该通知线程A继续生产,这就需要线程之间的协同通信。
java的Object对象提供了两个方法用于实现线程协同通信,wait();和notify();。
wait():在其他线程调用此对象的 notify() 方法或 notifyAll() 方法前,导致当前线程等待,并释放当前互斥锁。
notify() :唤醒在此对象监视器上等待的单个线程。如果所有线程都在此对象上等待,则会选择唤醒其中一个线程。选择是任意性的,并在对实现做出决定时发生。线程通过调用其中一个
wait
方法,在对象的监视器上等待。 以下是一段参考代码,实现了两个线程的交替运行:
import java.util.concurrent.atomic.AtomicInteger;public class TraditionalThreadCommunication {/** * @param args */public static void main(String[] args) {final Business business = new Business();new Thread(new Runnable() {@Overridepublic void run() {for(int i=1;i<=50;i++){business.sub(i);}}}).start();for(int i=1;i<=50;i++){business.main(i);}}} class Business { private boolean bShouldSub = true;//是否可以由sub运行。 public synchronized void sub(int i){ while(!bShouldSub){ try {this.wait();//不该sub方法运行时,让sub进入等待。} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();} }for(int j=1;j<=10;j++){System.out.println("sub thread sequence of " + j + ",loop of " + i);} bShouldSub = false; this.notify();//sub方法运行完毕后,通知main运行。 } public synchronized void main(int i){ while(bShouldSub){ try {this.wait();//不该main运行时,让main进入等待。} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();} }for(int j=1;j<=100;j++){System.out.println("main thread sequence of " + j + ",loop of " + i);}bShouldSub = true;this.notify();//main方法运行完毕后,通知sub运行。 } }
- 张孝祥java.concurrent线程并发学习笔记 - 传统线程回顾
- 张孝祥java.concurrent线程并发学习笔记 - concurrent简介
- 张孝祥java.concurrent线程并发学习笔记 - concurrent简介
- Java并发库(一):传统线程技术回顾
- 【Java多线程与并发库】1.传统线程技术回顾
- 【Java多线程与并发库】1.传统线程技术回顾
- 【张孝祥并发课程笔记】01:传统线程技术和定时器技术回顾
- 传统线程技术回顾
- 传统线程技术回顾
- 传统线程技术回顾
- Java多线程之传统线程回顾
- JUC线程-传统线程回顾
- 【张孝祥并发课程笔记】02:传统线程互斥技术
- 【张孝祥并发课程笔记】03:传统线程同步通信技术
- java.util.concurrent 学习笔记(2) 线程池基础
- 【java并发】传统线程同步通信技术
- 线程并发之回顾传统线程创建,定时器及线程间的通讯
- java线程并发笔记
- 中国内地摇滚歌手及代表作
- 放手的伤感日志分享:你单身,我等你。
- php JSON数组含中文,入库及读取
- sql distinct
- 一个程序员三十而立前的迷茫
- 张孝祥java.concurrent线程并发学习笔记 - 传统线程回顾
- 玩OpenNI的必不可少的工具是微软的Kinect或者华硕的Xtion
- 总体设计
- Beam搜素算法
- Android4.0源码在Eclipse调试
- sql distinct
- 最新网络流行伤感日志:如果我哭了,谁会心疼?
- redis2.4与2.6 性能比较
- [android]activity中每个方法用处