初始状态(New) : 线程对象被创建,即为初始状态。只在堆中开辟内存,与常规对象无异。
就绪状态(Ready) : 调用start()之后,进入就绪状态。等待OS选中,并分配时间片。
运行状态(Running) : 获得时间片之后,进入运行状态,如果时间片到期,则回到就绪状态。
终止状态(Terminated) : 主线程main()或独立线程run()结束,进入终止状态,并释放持有的时间片。
eg:
public class TestSleep {
public static void main(String[] args) {
SleepThread s1 = new SleepThread();
SleepThread s2 = new SleepThread();
s1.start();
s2.start();
}
static class SleepThread extends Thread {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(
Thread.currentThread().getName()+"..."+i
);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
}
eg:
public class TestYield {
public static void main(String[] args) {
YieldThread y1 = new YieldThread();
YieldThread y2 = new YieldThread();
y1.start();
y2.start();
}
static class YieldThread extends Thread{
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(
Thread.currentThread().getName()+"..."+i
);
//主动放弃CPU
Thread.yield();
}
}
}
}
内存分析:
eg:
public class TestJoin {
public static void main(String[] args) throws InterruptedException {
JoinThread j1 = new JoinThread();
j1.start();
//把j1加入到主线程中,造成主线程阻塞,直到j1执行完毕
j1.join();
for (int i = 0; i < 10; i++) {
System.out.println("主线程........"+i);
}
}
static class JoinThread extends Thread {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(
Thread.currentThread().getName()+"..."+i
);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
}
eg:
public class TestPriority {
public static void main(String[] args) {
PriorityThread p1 = new PriorityThread();
PriorityThread p2 = new PriorityThread();
PriorityThread p3 = new PriorityThread();
//线程优先级为1-10,默认为5,优先级越高,表示获取CPU机会越多
p1.setPriority(1);
p3.setPriority(10);
//优先级设置要在线程开始之前
p1.start();
p2.start();
p3.start();
}
static class PriorityThread extends Thread {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(
Thread.currentThread().getName()+"..."+i
);
}
}
}
}
eg:
public class TestInterrupt {
public static void main(String[] args) {
InterruptThread thread = new InterruptThread();
thread.start();
System.out.println("10秒内输入任意字符打断子进程休眠");
Scanner input = new Scanner(System.in);
input.next();
thread.interrupt();
}
static class InterruptThread extends Thread{
@Override
public void run() {
System.out.println("子线程开始休眠...");
try {
Thread.sleep(10000);
System.out.println("正常醒来");
} catch (InterruptedException e) {
System.out.println("被打醒了");
}
}
}
}
eg:
public class TestDaemon {
public static void main(String[] args) throws InterruptedException {
DaemonThread daemonThread = new DaemonThread();
//设置守护线程
daemonThread.setDaemon(true);//默认false,关闭
daemonThread.start();
for (int i = 0; i < 10; i++) {
System.out.println(
"主线程...."+i
);
Thread.sleep(1000);
}
}
static class DaemonThread extends Thread {
@Override
public void run() {
for (int i = 0; i < 20; i++) {
System.out.println(
Thread.currentThread().getName()+"..."+i
);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
}
需求:A线程将“Hello”存入数组;B线程将“World”存入数组。
线程不安全:
同步:一个线程接着一个线程等待执行。异步:多个线程并发同时执行。
语法:
同步代码块:
synchronized(锁对象){ //使用共享资源对象加锁
//同步代码(原子操作)
}
eg:
4个窗口共卖1000张票
Ticket:
public class Ticket implements Runnable{
private int count = 1000; //票数
@Override
public void run() {
while (true) {
//一般选择共享资源
synchronized (this) { //锁, 任何引用类型的对象都可以作为锁,但要保证唯一性
if (count<=0) {
break;
}
System.out.println(
Thread.currentThread().getName() +
"卖了第" + count + "张票"
);
count--;
}
}
}
}
Test:
public class Test {
public static void main(String[] args) {
Ticket ticket = new Ticket();
new Thread(ticket,"窗口1").start();
new Thread(ticket,"窗口2").start();
new Thread(ticket,"窗口3").start();
new Thread(ticket,"窗口4").start();
}
}
注意:
语法:
同步方法:
synchronized 返回值类型 方法名称(形参列表){ //对当前对象(this)加锁
// 代码(原子操作)
}
eg:
4个窗口共卖1000张票
Ticket:
public class Ticket implements Runnable{
private int count = 1000;
@Override
public void run() {
while (true) {
if (!sale()) {
break;
}
}
}
//同步方法
public synchronized boolean sale() {
if (count<=0) {
return false;
}
System.out.println(
Thread.currentThread().getName() +
"卖了第" + count + "张票"
);
count--;
return true;
}
}
注意:
注意:
已知JDK中线程安全的类:
eg:
你和你女朋友共用一张银行卡,你向卡中存钱,你女朋友从卡中取钱,使用程序模拟过程?
BankCard:
public class BankCard {
private double money;
public double getMoney() {
return money;
}
public void setMoney(double money) {
this.money = money;
}
}
Test:
public class Test {
public static void main(String[] args) {
BankCard card = new BankCard();
//匿名内部类
Runnable save = new Runnable() {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
synchronized (card) {
card.setMoney(card.getMoney() + 1000);
System.out.println(
Thread.currentThread().getName()+
"存了1000, 余额为"+card.getMoney()
);
}
}
}
};
//匿名内部类
Runnable take = new Runnable() {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
synchronized (card) {
if (card.getMoney() >= 1000) {
card.setMoney(card.getMoney() - 1000);
System.out.println(
Thread.currentThread().getName()+
"取了1000, 余额为"+card.getMoney()
);
} else {
System.out.println("赶紧存钱...");
i--;
}
}
}
}
};
new Thread(save,"小明").start();
new Thread(take,"小红").start();
}
}
注:JDK5之后就绪、运行统称Runnable
死锁:
eg:
吃饭问题
Test:
public class TestDeadLock {
public static void main(String[] args) {
new Boy().start();
new Girl().start();
}
static class Lock {
static Object LockA = new Object();
static Object LockB = new Object();
}
static class Boy extends Thread {
@Override
public void run() {
synchronized (Lock.LockA) {
System.out.println("Boy拿到了A锁");
synchronized (Lock.LockB) {
System.out.println("Boy拿到了B锁");
System.out.println("Boy可以吃饭了");
}
}
}
}
static class Girl extends Thread {
@Override
public void run() {
synchronized (Lock.LockB) {
System.out.println("Girl拿到了B锁");
synchronized (Lock.LockA) {
System.out.println("Girl拿到了A锁");
System.out.println("Girl可以吃饭了");
}
}
}
}
}
情况一: 死锁
Boy拿到了A锁
Girl拿到了B锁
情况二: 未死锁
Boy拿到了A锁
Boy拿到了B锁
Boy可以吃饭了
Girl拿到了B锁
Girl拿到了A锁
Girl可以吃饭了