凤翔网站开发软文广告经典案例300
Java多线程
- 进程
- 线程
- 线程的生命周期
- 创建线程
- 线程的优先级
- 线程调度器
进程
正在运行中的程序。每个进程都拥有自己(独立)的系统资源、内存空间和地址空间
线程
线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位。
线程的生命周期
新建状态(new )、可运行状态(runnable)、运行状态(running )、阻塞状态(blocked)、终止状态(dead)
- 当线程处于新建状态的时候,表明此时线程的对象实例已经被创建,但是尚未取得运行线程所需要的资源
- 产生了对象的实例之后,一旦调用线程的start()方法,则线程就会进入可运行状态,表明该线程已经获得运行时所需要的系统资源,具备了被调度执行的条件,从而使该线程可以被调度执行。
- 线程的运行状态是指线程被JVM线程调度程序分配了CPU执行时间,使用run() (在执行了start()之后,,run()自启动)方法可以使线程进入运行状态。正在运行的线程随时可能由JVM线程调度程序送回可运行状态。
- 当线程的run()方法执行完毕后进入终止状态,处于该状态的线程不会再被调度执行。
- 阻塞状态通常用于线程之间的通信与同步控制。
创建线程
Java程序中的线程被设计为一个对象,该对象具有自己的生命周期,可以利用接口java.lang.Runnable、类java.lang.Thread、Callable接口 创建一个线程
通过java.lang.Thread创建线程
继承Thread类,重写 run() 方法(必须重写)
public class ThreadDemo extends Thread {@Overridepublic void run() {System.out.println("当前线程的是:"+this.getName());}public static void main(String[] args) {ThreadDemo threadDemo = new ThreadDemo();threadDemo.start();}}
- 优点:程序代码相对简单,缺点:java 单继承使用场景限制
实现Runnable接口,实现 run() 方法
public class RunnableDemo implements Runnable {@Overridepublic void run() {System.out.println("当前线程的是:"+Thread.currentThread().getName());}public static void main(String[] args) {RunnableDemo runnableDemo = new RunnableDemo();new Thread(runnableDemo).start();}}
Runnable创建线程:通过把Runnable的一个子类的实例作为参数传递 给Thread类的一个构造方法
优点:
- 符合面向对象的设计思想
从面向对象的设计角度看,Thread类是虚拟CPU 的封装,因而Thread类的子类是关于CPU行为的类,但是在继承Thread类的子类大多都是与CPU不相关的类,而实现Runnable接口的方法将不会影响到Thread体系
- 实现了Runnable接口的类可以 用extends继承其他的类
Callable接口创建线程:实现Callable 接口,使用FutureTask 进行包装,通过Thread的构造方法传入futureTask实例
package com.callable;import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;public class ICallableTest implements Callable<Long> {@Overridepublic Long call() {Long id = Thread.currentThread().getId();System.out.println("当前的线程是"+Thread.currentThread().getName());return id;}public static void main(String[] args) throws ExecutionException, InterruptedException {ICallableTest ct = new ICallableTest();FutureTask futureTask = new FutureTask(ct);Thread t = new Thread(futureTask,"二货");t.start();System.out.println(futureTask.get());}
}
实现Callable接口的 call() 方法是带返回值(方法体中必须return )的,通过futureTask的 get() 获得
Callable和Runnable 的区别:
- Runnable的 run() 方法没有返回值,而Callable得 call() 方法有返回值,且支持泛型
- Runnable 接口 的 run() 方法只能抛出运行时候得异常,且无法捕获处理;Callable 接口 call 方法允许抛出异常(throws Exception),可以获取异常信息
线程的优先级
线程优先级是指优先级越高,越有可能先执行,但只是建议先执行,具体什么时候执行由系统决定(既不能绝对的说线程的调度是按照优先级进行调度的)
例如在windows系统中,当一个优先级为5且处于可运行状态的线程在等待CPU资源的时,系统可能正在执行一个优先级为3的线程
- 设置线程的优先级
public final void setPriority(int newPriority) ;
- 获取线程的优先级
public final int getPriority( );
- 在Thread 类中定义了线程优先级的取值范围(1~10)
//静态成员变量public static final int MIN_PRIORITY = 1;public static final int NORM_PRIORITY = 5;public static final int MAX_PRIORITY = 10;
优先级高只是建议先执行
Priority.java
public class Priority extends Thread {public Priority(String s){setName(s);}public void run(){System.out.println("线程:"+getName()+"----"+getPriority());}
}
PriorityTest.java
public class PriorityTest {public static void main(String[] args){Priority p1 = new Priority("线程 1");Priority p2 = new Priority("线程 2");Priority p3 = new Priority("线程 3");Priority p4 = new Priority("线程 4");p1.setPriority(1);p2.setPriority(2);p3.setPriority(3);p4.setPriority(4);p1.start();p2.start();p3.start();p4.start();}
}
线程调度器
Java提供了一个线程调度器来监视所有程序中的所有运行的线程,并决定哪个线程应该运行,哪个线程应该排队等待。在线程的 调度器的决策过程中,它可以识别线程的两个特征:一个是线程的优先级别,另一个是守护标志
- 守护线程:一般具有一个较低的优先级别,并且当计算机中运行的线程减少的时,为一个或多个程序提供一项基本的服务。例如垃圾收集线程就是一个不断运行的守护线程,它由于JVM提供,通过扫描程序查找不再被访问的变量,并把这些变量的资源释放给系统
- 调度器的基本原则:如果只有守护线程在运行,JVM将退出。新线程将从创建它的线程那里继承优先级别和守护标志,调度器通过分析所有线程的优先级来决定哪个线程先运行。具有较高优先级的线程,能够在较低优先级的 线程之前执行(但并不绝对)。