概念
进程:指一个内存中运行的应用程序,每个进程都有自己独立的一块内存空间,一个进程中可以启动多个线程。比如在Windows系统中,一个运行的exe就是一个进程。
线程:指进程中的一个执行流程,一个进程中可以运行多个线程。比如java.exe进程中可以运行很多线程。线程总是属于某个进程,进程中的多个线程共享进程的内存。
“同时”执行:是人的感觉,在线程之间实际上轮换执行。
Java中的线程
使用java.lang.Thread类或者java.lang.Runnable接口编写代码来定义、实例化和启动新线程。
一个Java应用总是从main()方法开始运行,main()方法运行在一个线程内,它被称为主线程。
Java线程:创建与启动
创建:扩展java.lang.Thread类,或实现java.lang.Runnable接口。通过重写run()方法来实现需要执行的业务逻辑;
实例化:通过new一个新的Thread对象来实例化该线程;
执行:调用Thread类的start()方法,启动新的执行线程(具有新的调用栈)。
其他:线程都可以设置名字,也可以获取线程的名字,连主线程也不例外。获取当前线程的对象的方法是:Thread.currentThread();
Java线程:线程状态的转换
Java线程:线程的调度
1、睡眠:Thread.sleep(long millis)和Thread.sleep(long millis, int nanos)静态方法强制当前正在执行的线程休眠(暂停执行)。当线程睡眠时,它入睡在某个地方;当睡眠时间到期,则返回到可运行状态。
2、让步:通过Thread.yield()来实现。yield()方法的作用是--让当前运行线程回到可运行状态,以允许具有相同优先级的其他线程获得运行机会。因此,使用yield()的目的是让相同优先级的线程之间能适当的轮转执行。
3、阻塞:Thread的非静态方法join()。例子:t.join()执行时,则当前运行的线程停止执行,直至线程t执行完毕后,再执行后续的剩余线程。
线程的同步与锁:
synchronized的使用
使用synchronized来同步需要同步的方法或数据块。
synchronized可以保证其管辖范围内的代码一次全部执行完毕(期间不会造成线程切换)。
synchronized需要获得相应对象的锁才能执行其管辖范围内的代码:
1、synchronized同步方法时,需要获得该方法所属的对象的锁;
2、synchronized同步静态方法时,需要获得该方法所属的类对象的锁;
3、synchronized同步数据块时,需要获得其()内的对象的锁。
线程交互的相关方法:
1、Object.wait():导致当前获得该对象的锁的线程等待,并释放出该对象的锁以供其他线程使用,当前线程等待直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法。
2、Object.notify():唤醒在此对象监视器上等待的单个线程。
3、Object.notifyAll():唤醒在此对象监视器上等待的所有线程。
经典的并发协作案例:
生产消费模型,参见连接 http://lavasoft.blog.51cto.com/62575/221932
线程池:
代码示例
Executors可以创建多种类型的线程池,示例中创建的是一个固定大小的线程池
通过调用ExecutorService对象的execute(Thread)方法,来将相应的线程提交给线程池,线程池会自动分配资源执行提交给它的所有线程
有返回值的线程Callable
可返回值的任务必须实现Callable接口;类似的无返回值的任务必须Runnable接口。
执行Callable任务后,可以获取一个Future的对象,在该对象上调用get就可以获取到Callable任务返回的Object了。
示例如下:
1、调用ExecutorService对象中的submit方法,将Callable实现的线程提交给线程池,线程返回的结果将保存在一个Future对象中;
2、调用Future对象的get()方法来获取相应线程的执行结果(返回值);
3、Callable对象中的call()方法用来实现有返回值的业务逻辑.
其他新特性:
1、Lock的使用,参见 http://lavasoft.blog.51cto.com/62575/222084
2、Condition的使用,参见 http://lavasoft.blog.51cto.com/62575/222536