例子部分参考验证:
https://blog.csdn.net/qq_34996727/article/details/80416277?utm_medium=distribute.pc_relevant.none-task-blog-OPENSEARCH-3.channel_param&depth_1-utm_source=distribute.pc_relevant.none-task-blog-OPENSEARCH-3.channel_param
1 实现线程执行单元
把标题从 1 创建线程 更新为 1 实现线程执行单元的方式。
java中只有Thread代表线程。Runnable只是将业务相关的代码抽象为一个接口。这涉及到一种设计模式:策略模式。
因此创建线程new线程的方式只有一种。
实现线程执行单元线程体的方式有两种。
例1.继承Thread类方式
代码:
package com
.whl
.thread
;
/**
* 注:
* java.lang包中放着java最核心最基础的类、接口:Object、System、Thread、Runnable
* Thread.currentThread()获取当前cpu执行线程
*/
public class TestThread {
public static void main(String
[] args
) {
/**
* step 3:在方法中新建一个刚才写的类
*/
MyThread myThread
= new MyThread();// 线程处于新建状态
myThread
.start();// 就绪状态
for(int i
= 0;i
/**
* step 2:复写java.lang.Thread中的run()方法
*/
@Override
public void run() {// 运行
// TODO 你的线程代码
for(int i
= 0;i
public static void main(String
[] args
) {
/**
* step 3:创建实现类
*/
MyRunnable myRunnable
= new MyRunnable();
/**
* step 4:创建Thread,传入实现类
*/
Thread thread
= new Thread(myRunnable
);
/**
* step 5:调用start()方法
*/
thread
.start();
for(int i
= 0;i
/**
* step 2:实现Runnable接口run()
*/
@Override
public void run() {
for(int i
= 0;i
public static void main(String
[] args
) {
/**
* step 3:创建线程,创建实现类中传递实参
*/
Thread t1
= new Thread(new MyRunnable2(23));
t1
.start();
int i
= 6;
while(i
-- > 0){
System
.out
.println(Thread
.currentThread().getName());
}
}
}
class MyRunnable2 implements Runnable {
/**
* step 1:在实现类中定义局部变量
*/
private int age
;
/**
* step 2:定义有参构造方法
* @param age
*/
public MyRunnable2(int age
) {
this.age
= age
;
}
@Override
public void run() {
int i
= 6;
while(i
-- > 0){
/**
* step 4:使用参数
*/
System
.out
.println(Thread
.currentThread().getName() + " 我的年龄是->" + age
);
}
}
}
运行结果

使用实现Runnable接口方式更好,原因:
java是单继承多实现;共享资源;数据和程序独立;
例4.两个线程共享资源实现代码:
package com
.whl
.thread
;
public class TestThread3 {
public static void main(String
[] args
) {
MyRunnable2 myRunnable2
= new MyRunnable2();
myRunnable2
.setAge(23);
// 两个线程共享变量age
Thread t1
= new Thread(myRunnable2
);
Thread t2
= new Thread(myRunnable2
);
t1
.start();
t2
.start();
int i
= 10;
while(i
-- > 0) {
System
.out
.println(Thread
.currentThread().getName());
}
}
}
class MyRunnable2 implements Runnable {
/**
* step 1:在实现类中定义局部变量
* 两个线程共享
*/
private int age
;
public int getAge() {
return age
;
}
public void setAge(int age
) {
this.age
= age
;
}
@Override
public void run() {
int i
= 10;
while(i
-- > 0){
this.age
++;
System
.out
.println(Thread
.currentThread().getName() + " 我的年龄是->" + age
);
}
}
}
运行结果:

3 线程应用例子
例5. 3个站台同时出售火车票,火车票共有20张
代码实现:
package com
.whl
.example
.station
;
/**
* 注明:
* static: 在类中的类前加上static,直接通过类名.类名调用;
* 在类中的方法前加上static,直接通过类名.方法名调用;
* 在类中的变量前加上static,直接同多类名.变量名访问;
* 静态变量生命周期是类的生命周期;
*
* step 1: 创建一个站台类继承java.lang.Thread
*/
public class Station extends Thread {
/**
* step 2: 创建有参构造方法,给线程名称赋值
* @param name
*/
public Station(String name
) {
super(name
);
}
/**
* step 3:创建静态变量,类的变量
*/
static int tick
= 20;
/**
* step 4: 创建静态钥匙,类的变量
*
* 关键思想:通过[静态,没有static关键字可正常运行]变量的占用判断是否对另一个静态变量操作
*/
Object lock
= "one";
/**
* step 5: 重写run()方法,实现买票操作
*/
@Override
public void run() {
while(tick
> 0) {
/**
* step 6: 每个线程使用同一静态变量,一个线程占用该静态变量时,其他线程不允许进入
* 该线程出来这个代码块后,不使用该静态变量
*
* 关键思想:synchronized与静态变量lock配合,操作系统保证cpu只运行三个线程中唯一一个线程中此段代码,
* 其他线程不能被执行。唯一一个线程的此段代码运行结束后,cpu可同步执行3个线程线程。
*/
synchronized (lock
) {
if(tick
> 0) {
System
.out
.println(getName()+"卖出了第"+tick
+"张票");
tick
--;
}else {
System
.out
.println("票卖完了");
}
}
try {
sleep(500);
} catch(Exception e
) {
e
.printStackTrace();
}
}
}
}
package com
.whl
.example
.station
;
public class Main {
public static void main(String
[] args
) {
/**
* step 7: 创建继承类售票窗口
* 3个窗口
*/
Thread t1
= new Station("售票窗口1号");
Thread t2
= new Station("售票窗口2号");
Thread t3
= new Station("售票窗口3号");
/**
* step 8: 三个窗口都处于就绪状态
*/
t1
.start();
t2
.start();
t3
.start();
}
}
运行结果:
问题:同步关键字为什么不写在循环外?
同步关键字写在循环外面代码:
@Override
public void run() {
synchronized (lock
){while(tick
> 0) {
/**
* step 6: 每个线程使用同一静态变量,一个线程占用该静态变量时,其他线程不允许进入
* 该线程出来这个代码块后,不使用该静态变量
*
* 关键思想:synchronized与静态变量lock配合,操作系统保证cpu只运行三个线程中唯一一个线程中此段代码,
* 其他线程不能被执行。唯一一个线程的此段代码运行结束后,cpu可同步执行3个线程线程。
*/
if(tick
> 0) {
System
.out
.println(getName()+"卖出了第"+tick
+"张票");
tick
--;
}else {
System
.out
.println("票卖完了");
}
try {
sleep(500);
} catch(Exception e
) {
e
.printStackTrace();
}
}
}}
运行结果:

结论:同步关键字修饰的代码块,被单独执行。
例6.两个人,一个人每次取钱100元,一个人每次取钱200元,账户里有1000元.
代码实现:
package com
.whl
.example
.person
;
import java
.util
.Objects
;
/**
* step 1:创建银行类
*/
public class Bank {
/**
* 创建一个账户,放1000元
* [有没有 static 不影响结果]
*/
double money
= 1000;
/**
* 提供柜台取钱方法
* @param money
*/
private void counter(double money
) {
this.money
-= money
;
System
.out
.println("柜台取钱"+money
+"元,还剩"+this.money
+"元!");
}
/**
* 提供atm取钱方法
* @param money
*/
private void atm(double money
) {
this.money
-= money
;
System
.out
.println("atm取钱"+money
+"元,还剩"+this.money
+"元!");
}
/**
* 核心:只要有一个线程被cpu正在执行这个取钱方法,其他都不准执行。
*
* 提供取钱方法,设置每次取钱金额,取钱方式
* @param money
* @param mode
* @throws Exception
*/
public synchronized void outMoney(double money
,String mode
) throws Exception
{
if(money
> this.money
) {
throw new Exception("取款金额"+money
+",余额只剩"+this.money
+",取款失败!");
}
if(Objects
.equals(mode
,"atm")) {
atm(money
);
}else {
counter(money
);
}
}
}
package com
.whl
.example
.person
;
/**
* step 2:创建一个人继承java.lang.Thread
*/
public class PersonA extends Thread {
Bank bank
;
String mode
;
public PersonA(Bank bank
,String mode
) {
this.bank
= bank
;
this.mode
= mode
;
}
/**
* 每次取钱100,柜台取钱
*/
public void run(){
while(bank
.money
>= 100) {
try{
bank
.outMoney(100,mode
);
}catch (Exception e
) {
e
.printStackTrace();
}
try{
sleep(100);
}catch (Exception e
) {
e
.printStackTrace();
}
}
}
}
package com
.whl
.example
.person
;
/**
* step 3:创建一个人继承java.lang.Thread
*/
public class PersonB extends Thread {
/**
* 创建账户
*/
Bank bank
;
/**
* 创建取钱方式
*/
String mode
;
/**
* 提供设置具体取钱方式及账户的方法
* @param bank
* @param mode
*/
public PersonB(Bank bank
,String mode
) {
this.bank
= bank
;
this.mode
= mode
;
}
/**
* 每次取钱200元,atm取钱
*/
public void run(){
while(bank
.money
>= 200) {
try{
bank
.outMoney(200,mode
);
}catch (Exception e
) {
e
.printStackTrace();
}
try{
sleep(100);
}catch (Exception e
) {
e
.printStackTrace();
}
}
}
}
package com
.whl
.example
.person
;
/**
* step 4:创建一个入口类
*/
public class Main {
public static void main(String
[] args
) {
/**
* 实例化一个银行账户
*/
Bank bank
= new Bank();
/**
* 实例化两个继承类,共享这个银行账户
*/
PersonA personA
= new PersonA(bank
,"counter");
PersonB personB
= new PersonB(bank
,"atm");
/**
* 线程处于就绪状态
*/
personA
.start();
personB
.start();
}
}
运行结果:

例7.龟兔赛跑
总共200米
乌龟0.1秒跑2米,不休息
兔子0.1秒跑5米,每20米休息1秒
一个赢了,另一个停止跑
实现代码:
package com
.whl
.example
.animal
;
public abstract class Animal extends Thread {
/**
* 比赛长度
*/
public int length
= 200;
/**
* 抽象方法
* 动物跑
*/
public abstract void running();
/**
* 复写run()
*/
public void run(){
super.run();
while (length
> 0) {
running();
}
}
/**
* 抽象类中声明一个接口
*/
public static interface Calltoback {
public void win();
}
/**
* 创建接口对象
*/
public Calltoback calltoback
;
}
package com
.whl
.example
.animal
;
public class Rabbit extends Animal {
public Rabbit() {
setName("兔子");
}
@Override
public void running() {
int dis
= 5;
length
-= dis
;
System
.out
.println("兔子跑了"+dis
+"米,距离终点还有"+length
+"米");
if(length
calltoback
.win();
}
}
try {
if((2000 - length
) % 20 == 0) {// 每20米休息一次
sleep(1000);
}else {
sleep(100);// 每0.1秒跑5米
}
}catch (Exception e
) {
e
.printStackTrace();
}
}
}
package com
.whl
.example
.animal
;
public class Tortoise extends Animal {
public Tortoise() {
setName("乌龟");
}
@Override
public void running() {
int dis
= 2;
length
-= dis
;
System
.out
.println("乌龟跑了"+dis
+"米,距离终点还有"+length
+"米");
if(length
calltoback
.win();
}
}
try {
sleep(100);// 跑2米停0.1秒 -> 每0.1秒跑2米
} catch (Exception e
) {
e
.printStackTrace();
}
}
}
package com
.whl
.example
.animal
;
public class LetOneStop implements Animal.Calltoback {
Animal animal
;
public LetOneStop(Animal animal
) {
this.animal
= animal
;
}
public void win(){
// 线程停止
animal
.stop();
}
}
package com
.whl
.example
.animal
;
public class Main {
public static void main(String
[] args
) {
// 乌龟
Tortoise tortoise
= new Tortoise();
// 兔子
Rabbit rabbit
= new Rabbit();
// 兔子赢了,将乌龟停止
LetOneStop letOneStop1
= new LetOneStop(tortoise
);
rabbit
.calltoback
= letOneStop1
;
// 乌龟赢了,将兔子停止
LetOneStop letOneStop2
= new LetOneStop(rabbit
);
tortoise
.calltoback
= letOneStop2
;
// 跑
tortoise
.start();
rabbit
.start();
}
}
运行结果:
