创建一个线程 相当于CPU开辟了一个独立的执行路径
每个执行路径都是一个独立的空间
创建一个线程 该线程就会拥有一个独立的栈空间
如果在同一个栈空间中 不符合先入栈后出栈规则
线程的六种状态
1.新建状态(new 线程对象)
2.运行状态(调用 start方法)
3.受阻塞状态(等待CPU的执行资源)
4.休眠状态(调用了sleep(时间)方法)
5.等待状态(调用了wait方法)
6.死亡状态(润方法执行完毕)
匿名内部类
相当于创建一个该类的子类的对象
new 父类类名或接口名(){
重写父类的方法
};
public class Demo {
public static void main(String[] args){
// 创建Test类的子类对象
// 这里可以直接new Test(){}
// 但是这样这个对象没有名字 是匿名对象
// 可以接收一下
Test test = new Test(){
//重写父类的方法
@Override
public void fun(){
System.out.println("我是子类的fun方法");
}
};
// 调用子类方法
test.fun();
}
}
class Test{
public void fun(){
System.out.println("我是父类的fun方法");
}
}
public class Demo {
public static void main(String[] args) {
// 创建接口的实现类
new TestInter() {
@Override
public void fun(){
System.out.println("我是实现类的 fun方法");
}
}.fun();
}
}
interface TestInter {
public abstract void fun();
}
匿名内部类方式创建线程
方式1
public class Demo {
public static void main(String[] args) {
new Thread() {
@Override
public void run() {
System.out.println("我是创建线程方式1");
}
}.start();
Runnable runnable = new Runnable() {
@Override
public void run() {
System.out.println("我是创建线程方式2");
}
};
//放入线程对象中
Thread thread = new Thread(runnable);
thread.start();
new Thread(new Runnable() {
@Override
public void run(){
System.out.println("我是创建线程方式3");
}
}).start();
}
}
线程休眠
public class Demo {
public static void main(String[] args) throws InterruptedException {
SleepThread sleepThread = new SleepThread();
sleepThread.start();
for (int i = 0; i < 100; i++) {
// 线程休眠1s 单位是 毫秒
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName() + i);
}
}
}
class SleepThread extends Thread{
@Override
public void run() {
for (int i = 0; i < 50; i++) {
// 休眠1s
// 如果在子线程中出现异常 只能try...catch处理
/*
* Thread类是Runnable接口的实现类
* 重写了接口中的run方法
* 该方法 没有抛出异常
* 所以 所有Runnable接口的实现类(包括Thread类)
* 都不能在run方法中 抛出异常 只能处理
*/
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + i);
}
}
}
同步锁
/*
* 卖火车票问题
*/
public class Demo05 {
public static void main(String[] args) {
TicketsRunnable tr = new TicketsRunnable();
// 创建3个线程 这个线程 会执行run方法(这个线程的任务)
Thread t1 = new Thread(tr);
Thread t2 = new Thread(tr);
Thread t3 = new Thread(tr);
// 开启这三个线程
t1.start();
t2.start();
t3.start();
}
}
/*
* 同步锁(同步代码块)
* 锁 可以是任意对象 要保证 锁的唯一 三个线程都使用的是同一把锁
*
*
* synchronized (对象锁) {
}
*/
class TicketsRunnable implements Runnable{
//声明50张票 保证票是共享数据 只new 一次该类对象
private int tickets = 50;
// 创建了对象锁 保证唯一
private Object obj = new Object();
//卖票方法
@Override
public void run() {
while (true) {
// 锁只要保证是对象和唯一 就可以 (填this也可以)
synchronized (obj) {
// 操作的共享数据的代码
if (tickets > 0) {
// 线程休眠一会儿
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// 有票就卖一张
System.out.println(Thread.currentThread().getName() + "--" + tickets);
// 减少一张
tickets--;
}else {
// 没票 结束循环
break;
}
}
// 让线程 让出CPU的资源
// 不是一定让出 有几率
Thread.yield();
}
}
}
方法中添加 synchronized 关键词
*
* 同步锁规则:
* 如果有锁 可以进同步代码块 携带锁进去
* 当线程执行完同步代码块中的代码 把锁还回去
* 如果没有锁 线程需要在同步代码块外等待 遇到锁才可以近同步代码块
*/
public class Demo06 {
public static void main(String[] args) {
TicketsRunnable1 tr1 = new TicketsRunnable1();
// 创建3个线程 这个线程 会执行run方法(这个线程的任务)
Thread t1 = new Thread(tr1);
Thread t2 = new Thread(tr1);
Thread t3 = new Thread(tr1);
// 开启这三个线程
t1.start();
t2.start();
t3.start();
}
}
class TicketsRunnable1 implements Runnable {
// 声明50张票 保证票是共享数据 只new 一次该类对象
private int tickets = 50;
// 创建了对象锁 保证唯一
private Object obj = new Object();
// 卖票方法
@Override
public void run() {
while (true) {
if (sellTickets()) {
break;
}
// 让出CPU资源
Thread.yield();
}
}
// 操作共享数据的方法
// 在方法中 添加 synchronized 关键词
public synchronized boolean sellTickets() {
// 操作的共享数据的代码
if (tickets > 0) {
// 线程休眠一会儿
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// 有票就卖一张
System.out.println(Thread.currentThread().getName() + "--" + tickets);
// 减少一张
tickets--;
return false;
} else {
// 没票 结束循环
return true;
}
}
}
静态的同步代的码锁
public class Demo06 {
public static void main(String[] args) {
TicketsRunnable1 tr1 = new TicketsRunnable1();
// 创建3个线程 这个线程 会执行run方法(这个线程的任务)
Thread t1 = new Thread(tr1);
Thread t2 = new Thread(tr1);
Thread t3 = new Thread(tr1);
// 开启这三个线程
t1.start();
t2.start();
t3.start();
}
}
class TicketsRunnable1 implements Runnable {
// 声明50张票 保证票是共享数据 只new 一次该类对象
private static int tickets = 50;
// 创建了对象锁 保证唯一
private Object obj = new Object();
// 卖票方法
@Override
public void run() {
while (true) {
if (sellTickets()) {
break;
}
// 让出CPU资源
Thread.yield();
}
}
//静态方法的同步代码的锁 可以使用本类 类名.class
public static boolean sellTickets() {
synchronized (TicketsRunnable1.class) {
// 操作的共享数据的代码
if (tickets > 0) {
// 线程休眠一会儿
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// 有票就卖一张
System.out.println(Thread.currentThread().getName() + "--" + tickets);
// 减少一张
tickets--;
return false;
} else {
// 没票 结束循环
return true;
}
}
}
}
死锁
/*
* 模拟线程死锁
* 1.需要两个锁对象( 保证唯一)
*/
public class Demo07 {
public static void main(String[] args) {
DeathLockRunnable dlr = new DeathLockRunnable();
Thread t1 = new Thread(dlr);
Thread t2 = new Thread(dlr);
t1.start();
t2.start();
}
}
// A锁
class LockA {
// 私有构造方法
private LockA() {
}
// 定义一个常量 作为 锁对象 不能修改 也不能创建
public static final LockA LOCK_A = new LockA();
}
// B锁
class LockB{
//私有构造方法
private LockB() {
}
// 定义一个常量 作为 锁对象 不能修改 也不能创建
public static final LockB LOCK_B = new LockB();
}
class DeathLockRunnable implements Runnable{
// 声明一个标识
// 标记一次是先A后B
// 一次是先B后A
private boolean isTrue = true;
@Override
public void run() {
// 死循环(增加死锁的几率)
while (true) {
if (isTrue) {
// A --> B
synchronized (LockA.LOCK_A) {
System.out.println("if...LOCK_A");
synchronized (LockB.LOCK_B) {
System.out.println("if...LOCK_B");
}
}
} else {
// B --> A
synchronized (LockB.LOCK_B) {
System.out.println("else...LOCK_B");
synchronized (LockA.LOCK_A) {
System.out.println("else...LOCK_A");
}
}
}
// 修改标记
isTrue = !isTrue;
}
}
}
Lock 接口
Lock 是jdk1.5之后出现的锁
使用Lock锁
Lock.lock();
try{
写操作共享数据的代码
}finally{
lock.unlock();
}
public class Demo {
public static void main(String[] args) {
Tickets3 tickets3 = new Tickets3();
Thread t1 = new Thread(tickets3);
Thread t2 = new Thread(tickets3);
Thread t3 = new Thread(tickets3);
t1.start();
t2.start();
t3.start();
}
}
class Tickets3 implements Runnable{
private int tickets = 50;
//声明锁对象
private ReentrantLock lock = new ReentrantLock();
@Override
public void run() {
while (true) {
// 加锁
lock.lock();
try {
// 锁住操作共享数据的代码
if (tickets > 0) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ":" + tickets);
tickets--;
}else {
break;
}
} finally {
// 解锁
lock.unlock();
}
// 让出CPU资源
Thread.yield();
}
}
}
接口实现创建线程的好处
1.避免直接集成Thread类的局限性(避免单继承)
2.接口即插即用 减少类与类之间联系(可以解耦)
Day.29