进程与线程
1、线程:程序中单独顺序的控制流
线程本身是依靠程序进行运行
线程是程序中的顺序控制流,只能使用分配给程序的资源和环境
2、进程:执行中的程序
一个进程可以包含一个或多个线程
一个进程至少要包含一个线程
3、单线程:
程序中只存在一个线程,实际上主方法就是一个主线程
4、多线程:
多线程是在一个程序中运行多个任务
多线程的目的是更好的使用CPU资源
线程的实现:
1、java对线程的2种实现:集成Thread类
、实现 Runnable接口
2、Thread类:
Thread类是在java.lang包中定义,集成Thread类必须重写run()方法
public class MyThread extends Thread {
private String name;
public MyThread(String name) {
this.name = name;
}
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
System.out.println(name + " : " + i);
}
}
}
public class ThreadDemo {
public static void main(String[] args) {
MyThread t1 = new MyThread("A");
MyThread t2 = new MyThread("B");
// 并发执行 两个线程
t1.start();
t2.start();
}
}
3、Runnable接口
public class MyRunnable implements Runnable {
private String name;
public MyRunnable(String name) {
this.name = name;
}
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
System.out.println(name + ":" + i);
}
}
}
public class ThreadDemo02 {
public static void main(String[] args) {
MyRunnable r1 = new MyRunnable("A");
MyRunnable r2 = new MyRunnable("B");
// 由于 Runnable没有类似start的方法,所以集成自Runnable的接口需要使用Thread对象来调用
Thread t1 = new Thread(r1);
Thread t2 = new Thread(r2);
// 并发执行 两个线程
t1.start();
t2.start();
}
}
线程的状态
线程状态 | 作用 |
---|---|
创建状态 | 准备好一个多线程的对象 |
就绪状态 | 准备 start() 方法,等待 CPU 进行调度 |
运行状态 | 执行 run() 方法 |
阻塞状态 | 暂时停止执行,可能将资源交给其他线程执行 |
终止状态(死亡状态) | 线程销毁 |
线程的常用方法
方法名 | 作用 |
---|---|
getName() | 获取线程名称 |
currentThread() | 获取当前线程对象 |
isAlive() | 判断线程是否启动 |
join() | 线程的强行运行 |
sleep() | 线程的休眠 |
yield() | 线程的礼让 |
class RunnableDemo implements Runnable {
private String name;
public RunnableDemo(String name) {
this.name = name;
}
@Override
public void run() {
for (int i = 0; i < 50; i++) {
// 使线程沉睡1s再打印
try {
Thread.sleep(1);
// 获取当前线程对象
System.out.println("当前线程对象:" + Thread.currentThread().getName() + " " + name + " : " + i);
if (i == 10) {
System.out.println("礼让");
// 线程的礼让
Thread.yield();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class ThreadDemo03 {
public static void main(String[] args) {
RunnableDemo r = new RunnableDemo("A");
RunnableDemo r2 = new RunnableDemo("B");
Thread t = new Thread(r);
Thread t2 = new Thread(r2);
// 判断线程是否运行
System.out.println(t.isAlive());
t.start();
t2.start();
System.out.println(t.isAlive());
// 线程的强制运行
for (int i = 0; i < 50; i++) {
if (i > 10) {
try {
t.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("主线程:" + i);
}
}
}
线程的优先级
1、优先级顺序设置:如果说明都不设置默认值是5
1
- MIN_PRIORITY
10
- MAX_PRIORITY
5
- NORM_PRIORITY
class ThreadRun implements Runnable {
@Override
public void run() {
for (int i = 0; i < 5; i++) {
try {
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName() + ":" + i);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class ThreadDemo04 {
public static void main(String[] args) {
Thread t1 = new Thread(new ThreadRun(), "A");
Thread t2 = new Thread(new ThreadRun(), "B");
Thread t3 = new Thread(new ThreadRun(), "C");
// 设置线程优先级
t1.setPriority(Thread.MIN_PRIORITY);
t2.setPriority(Thread.NORM_PRIORITY);
t3.setPriority(Thread.MAX_PRIORITY);
// 启动线程
t1.start();
t2.start();
t3.start();
}
}
同步和死锁
1、同步代码块
在代码块上加上 synchronized
关键字,此代码块就称为 同步代码块
2、块同步格式:
synchronized(同步对象) {
需要同步的代码块;
}
3、同步方法:块可以同步,方法也能同步
4、方法同步格式:
synchronized void 方法名称() {}
5、同步代码块和同步方法的使用:以三个窗口同时卖票为例,假设现在一共有5张票
class MyThreadDemo implements Runnable {
private int ticket = 5;
@Override
public void run() {
for (int i = 0; i < 10; i++) {
// ticket资源共享了,此时使用synchronized同步代码块
synchronized (this) {
if (ticket > 0) {
try {
// 车票卖出的等待时间
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("车票:" + ticket--);
}
}
// 调用同步方法
tell();
}
}
// 同步方法
public synchronized void tell() {
if (ticket > 0) {
try {
// 车票卖出的等待时间
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("车票:" + ticket--);
}
}
}
public class ThreadDemo05 {
public static void main(String[] args) {
MyThreadDemo m = new MyThreadDemo();
Thread t1 = new Thread(m);
Thread t2 = new Thread(m);
Thread t3 = new Thread(m);
t1.start();
t2.start();
t3.start();
}
}