目录
进程
进程:是正在运行的程序
- 是系统进行资源分配和调用法人独立单位
- 每一个进程都有它自己的内存空间和系统资源
线程
线程:是进程中的单个顺序控制流,是一条执行路径
- 单线程:一个进程如果只有一条执行路径,则称为单线程程序
- 多线程:一个程序如果有多条执行路径,则称为多线程程序
实现多线程的方法
方式一:继承Thread类
- 定义一个类MyThread继承Thread类
- 在MyThread类中重写run()方法
- 创建MyThread类的对象
- 启动线程
public class MyThread extends Thread{
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(i);
}
/**
* 为什么要重写run()方法
* run()方法是用来封装被线程执行的代码
* */
}
}
public class MyThreadDemo {
public static void main(String[] args) {
MyThread my1 = new MyThread();
MyThread my2 = new MyThread();
/* my1.run();
my2.run();*/
my1.start();
my2.start();
/**
*run()方法和start()方法的区别
* run():封装线程执行的代码,直接调用,相当于普通方法的调用
* start():启动线程,然后有jvm调用此线程的run方法
* */
}
}
Thread类的常用方法
方法 | 说明 |
---|---|
void run() | 执行任务操作的方法 |
void start() | 使该线程开始执行 |
void sleep(long millis) | 在指定的毫秒数内让当前正在执行的线程休眠(暂停执行) |
String getName() | 返回该线程名称 |
int getPriority | 返回改线程的优先级 |
void setPriority(int newPriority) | 更改该线程的优先级 |
Thread.State getStata() | 返回该线程的状态 |
boolean isAlive() | 测试线程是否处于活动状态 |
void join() | 等待该线程终止 |
void interrupt() | 中断线程 |
void yield() | 暂停当前正在执行的线程对象,并执行其他线程 |
设置和获取线程名称
Thread类中设置和获取进程名称的方法
方法一:
- setName(String name):将此线程的名称更改为等于参数name
- String getName():返回此线程的名称
方法二 :
- Thread类的有参构造来设置名称,通过getName获取值
方法三:
- 静态的currentThread()的方法得到当前正在执行的线程对象,通过这个对象去调用getName()获取线程名称
public class MyThread extends Thread {
public MyThread() {
}
public MyThread(String name) {
super(name);
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(getName() + ":" + i);
}
}
}
public class MyThreadDemo {
public static void main(String[] args) {
MyThread my1 = new MyThread();
MyThread my2 = new MyThread();
my1.setName("线程一:");
my2.setName("线程二:");
//Thread(String name)
MyThread my1 = new MyThread("线程一:");
MyThread my2 = new MyThread("线程二:");
my1.start();
my2.start();
//currentThread()返回当前正在执行的线程对象的引用
System.out.println(Thread.currentThread().getName());//main
}
线程调度
线程有两种调度模型
- 分时调度模型:所有的线程轮流使用CPU的使用权,平均分配每个线程占用 CPU的时间片
- 抢占式调度模型:优先让优先级高的线程使用CPU,如果线程的优先级相同,那么会随机选择一个,优先级高的线程获取的CPU时间片相对多一些
Java使用的是抢占式调度模型
多线程程序执行是有随机性的,因为谁抢到CPU的使用权是不一定的
Thread类中设置和获取线程优先级的方法
- public final int getPriority():返回此线程的优先级
- public final void setPriority(int newPriority):更改此线程的优先级
线程默认优先级是:5;线程的优先级范围是:1-10
线程优先级高仅仅表示线程获取CPU时间片的几率高
public class MyThread extends Thread {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(getName() + ":" + i);
}
}
}
public class MyThreadDemo {
public static void main(String[] args) {
MyThread my1 = new MyThread();
MyThread my2 = new MyThread();
MyThread my3 = new MyThread();
//setName(String name):将此线程的名称更改为等于参数name
my1.setName("线程一:");
my2.setName("线程二:");
my3.setName("线程三:");
/**
//public final int getPriority():返回此线程的优先级
int priority = my1.getPriority();
int priority1 = my2.getPriority();
int priority2 = my3.getPriority();
System.out.println(priority);//5
System.out.println(priority1);//5
System.out.println(priority2);//5
//public final void setPriority(int newPriority):更改此线程的优先级
System.out.println(Thread.MAX_PRIORITY);//10
System.out.println(Thread.MIN_PRIORITY);//1
System.out.println(Thread.NORM_PRIORITY);//5
*/
my1.setPriority(Thread.MIN_PRIORITY);
my2.setPriority(Thread.MAX_PRIORITY);
my3.setPriority(Thread.NORM_PRIORITY);
my1.start();
my2.start();
my3.start();
}
}
线程控制
方法名 | 说明 |
---|---|
void sleep(long millis) | 使当前正在执行的线程停留(暂停执行)指定的毫秒数 |
void jion | 等待这个进程死亡 |
void setDaemon(boolean on) | 将此线程标记为守护线程,当运行的线程都是守护线程时,Java虚拟机将退出 |
/**
sleep&join
*/
public class MyThread2 implements Runnable {
@Override
public void run() {
System.out.println("线程正在运行,处于运行状态");
System.out.println("线程开始休眠,线程阻塞状态");
try {
Thread.sleep(5000);
System.out.println("线程休眠结束,线程阻塞状态结束,再次进入就绪状态");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
MyThread2 runable = new MyThread2();
Thread thread = new Thread(runable);
System.out.println("线程处于创建状态!");
thread.start();
System.out.println("线程处于就绪状态!");
}
}
public class JoinTest {
public static void main(String[] args) {
MyThread2 runable = new MyThread2();
Thread t = new Thread(runable, "mythread2");
t.start();
//循环打印,main做的事
for (int i = 1; i <= 20; i++) {
System.out.println(Thread.currentThread().getName()+" : "+i);
if (i==3){
try {
t.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
Thread.yield();
t.interrupt();
}
}
}
}
/**
setDaemon
*/
public class ThreadDaemon extends Thread {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(getName() + ":" + i);
}
}
public static void main(String[] args) {
ThreadDaemon td1 = new ThreadDaemon();
ThreadDaemon td2 = new ThreadDaemon();
td1.setName("线程一");
td2.setName("线程二");
//设置主线程为线程主
Thread.currentThread().setName("线程主");
//设置守护线程
td1.setDaemon(true);
td2.setDaemon(true);
td1.start();
td2.start();
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName()+":"+i);
}
}
}
线程的状态(生命周期)
线程的生命周期可以分为4个阶段,即线程的4种状态,分别为新生状态,可运行状态,阻塞状态和死亡状态。一个具有生命的线程,总是处于4种状态之一。
方式二:实现Runnable接口
- 定义一个类MyRunnable实现Runnable接口
- 在MyRunnable类中重写run()方法
- 创建MyRunnable类的对象
- 创建Thread类的对象,把MyRunnable对象作为构造方法的参数
- 启动线程
public class MyRunnableDemo implements Runnable{
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName()+":"+i);
}
}
public static void main(String[] args) {
//创建MyRunnable类的对象
MyRunnableDemo mr = new MyRunnableDemo();
//创建Thread类的对象,把MyRunnable对象作为构造方法的参数
//Thread(Runnable target)
// Thread t1 = new Thread(mr);
// Thread t2 = new Thread(mr);
//Thread(Runnable target,String name)
Thread t1 = new Thread(mr, "线程一");
Thread t2 = new Thread(mr, "线程二");
t1.start();
t2.start();
}
}
多线程的实现方案有两种:
- 继承Thread
- 实现Runnable接口
相比继承Thread类,实现Runnable接口的好处:
- 避免了Java单继承的局限性
- 适合多个相同程序的代码去处理同一资源的情况,把线程和程序代码、数据有效分离,较好的体现了面向对象的设计思想