JAVA 多线程
多线程的四种方式
继承Thread类、实现Runnable接口、实现Callable接口通过FutureTask包装器来创建Thread线程、使用ExecutorService、Callable、Future实现有返回结果的多线程。
其中前两种方式线程执行完后都没有返回值,后两种是带返回值的。
1、继承Thread类创建线程
2、实现Runnable接口创建线程
1 2 3 4 5 6 7 8 | public class MyThread extends OtherClass implements Runnable { public void run() { System.out.println("MyThread.run()"); } } MyThread myThread = new MyThread(); Thread thread = new Thread(myThread); thread.start(); |
3、实现Callable接口通过FutureTask包装器来创建Thread线程
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | public interface Callable<V> { V call() throws Exception; } public class SomeCallable<V> extends OtherClass implements Callable<V> { @Override public V call() throws Exception { // TODO Auto-generated method stub return null; } } Callable<V> oneCallable = new SomeCallable<V>(); //由Callable<Integer>创建一个FutureTask<Integer>对象: FutureTask<V> oneTask = new FutureTask<V>(oneCallable); //注释:FutureTask<Integer>是一个包装器,它通过接受Callable<Integer>来创建,它同时实现了Future和Runnable接口。 //由FutureTask<Integer>创建一个Thread对象: Thread oneThread = new Thread(oneTask); oneThread.start(); //至此,一个线程就创建完成了。 |
4、使用ExecutorService、Callable、Future实现有返回结果的线程
ExecutorService submit Callable后返回 Future 获取线程信息和结果
submit Runnable 则只能获取线程信息 无返回结果
Executors提供四种线程池,分别为:
newCachedThreadPool
创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
newFixedThreadPool
创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
newScheduledThreadPool
创建一个定长线程池,支持定时及周期性任务执行。
newSingleThreadExecutor
创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行
进程:每个进程都有独立的代码和数据空间(进程上下文),进程间的切换会有较大的开销,一个进程包含1--n个线程。(进程是资源分配的最小单位)
线程:同一类线程共享代码和数据空间,每个线程有独立的运行栈和程序计数器(PC),线程切换开销小。
线程和进程一样分为五个阶段:创建、就绪、运行、阻塞、终止。
start方法重复调用的话,会出现java.lang.IllegalThreadStateException异常。
实现Runnable接口比继承Thread类所具有的优势:
1):适合多个相同的程序代码的线程去处理同一个资源
2):可以避免java中的单继承的限制
3):增加程序的健壮性,代码可以被多个线程共享,代码和数据独立
4):线程池只能放入实现Runable或callable类线程,不能直接放入继承Thread的类
①sleep(long millis): 在指定的毫秒数内让当前正在执行的线程休眠(暂停执行)
②join():指等待t线程终止。
③yield():暂停当前正在执行的线程对象,并执行其他线程。当前运行线程回到可运行状态
④setPriority(): 更改线程的优先级。
Thread.sleep()与Object.wait()二者都可以暂停当前线程,释放CPU控制权,主要的区别在于Object.wait()在释放CPU同时,释放了对象锁的控制。sleep() 不释放锁