进程与线程
一个程序有一个进程
一个进程包含多个线程(必须有一个主线程)
查看线程
Thread t = Thread.currentThread();//获得当前线程
线程创建方式
1.继承Thread类,重写run方法,调用start方法
2.实现Runnable接口,重写run方法,创建Thread对象new Thread(Runnable),调用start方法
2.实现Callable<数据类型>,重写call方法 注意:Callable有返回值
package ch03.com.hz.ch08.test01;
public class MyThread extends Thread {
public void run() {
for(int i =1;i<=20;i++) {
System.out.println("打印了第"+i+"次");
}
}
}
package ch03.com.hz.ch08.test02;
public class Run implements Runnable{
public static Thread t;
@Override
public void run() {
for(int i =1;i<=20;i++) {
System.out.println("打印了第"+i+"次");
}
}
}
package ch03.com.hz.ch08.test03;
import java.util.concurrent.Callable;
public class Call implements Callable<String>{
@Override
public String call() throws Exception {
for(int i =1;i<=20;i++) {
System.out.println("打印了第"+i+"次");
}
return "打印成功";
}
}
线程状态
创建状态:new 一个就是创建
就绪状态:调用start方法就是就绪状态
运行
当线程获得CPU时间片后,就会进入运行状态,开始执行run方法。
4
阻塞
当遇到以下几种情况,线程会从运行状态进入到阻塞状态。
- 调用sleep方法,使线程睡眠。
- 调用wait方法,使线程进入等待。
- 当线程去获取同步锁的时候,锁正在被其他线程持有。
- 调用阻塞式IO方法时会导致线程阻塞。
- 调用suspend方法,挂起线程,也会造成阻塞。
需要注意的是,阻塞状态只能进入就绪状态,不能直接进入运行状态。因为,从就绪状态到运行状态的切换是不受线程自己控制的,而是由线程调度器所决定。只有当线程获得了CPU时间片之后,才会进入运行状态。
5) 死亡
当run方法正常执行结束时,或者由于某种原因抛出异常都会使线程进入死亡状态。另外,直接调用stop方法也会停止线程。但是,此方法已经被弃用,不推荐使用。
线程调度
|---------------------------------------------------------|---------------------------|
| 方 法 | 说 明 |
| void setPr i ority(int newPriority) | 更改线程的优先级 |
| static void sleep(long millis) | 在指定的毫秒数内让当前正在执行的线程休眠 |
| void join() | 等待该线程终止 |
| static void yield() | 暂停当前正在执行的线程对象,并执行其他线程 |
| void interrupt() | 中断线程 |
| boolean isAlive() | 测试线程是否处于活动状态 |
强制执行:可能需要来回传参
package ch03.com.hz.ch08.test04;
public class PuTong implements Runnable{
public Thread t1;
public Thread t2;
public void run() {
t1.setPriority(1);
for(int i =1;i<=50;i++) {
if(Thread.currentThread().getName().equals("普通号")&&i==10) {
try {
t2.join();
} catch (InterruptedException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName()+":"+i+"号病人正在看病!");
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
}
多线程同步可能会引发线程不安全,因此我们需要用到锁
锁
1.代码锁2.方法锁
package ch03.com.hz.ch08.test06;
import java.util.concurrent.CountDownLatch;
public class MaiPiao implements Runnable{
int num = 0;
int count =10;
@Override
public void run() {
while(true) {
synchronized (this) {
if(count>0) {
num++;
count--;
}else {
break;
}
System.out.println(Thread.currentThread().getName()+"抢到第"+num+"张票,剩余"+count+"张票!");
}
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
}
}
线程安全
|-----------|------------|----------|---------------|
| | 方法是否同步 | 效率比较 | 适合场景 |
| 线程安全 | 是 | 低 | 多线程并发共享资源 |
| 非线程安全 | 否 | 高 | 单线程 |
Hashtable && HashMapHashtable继承关系实现了Map接口
Hashtable继承Dictionary类线程安全,效率较低
键和值都不允许为null
HashMap继承关系实现了Map接口,继承AbstractMap类
非线程安全,效率较高
键和值都允许为null