继承Thread的方式实现多线程
public class TestThread extends Thread{
@Override
public void run() {
System.out.println("多线程运行的代码");
for(int i = 0; i < 5; i++){
System.out.println("这是多线程的逻辑代码:" + i);
}
}
}
-------------------------------
public class Test {
public static void main(String[] args) {
Thread t0 = new TestThread();
t0.start();
System.out.println("---------------1");
System.out.println("---------------2");
System.out.println("---------------3");
}
}
解析
- 多次运行这个main方法之后 我们发现main方法中打印的3行与开启线程运行run方法中的打印语句是混合起来
- 而且main方法中的打印与run方法中打印语句顺序是不固定的 为什么呢?
- main执行t0.start()方法开启多线程之后,就相当于在main方法之外开启一个支流
- 这个个时候t0.start()的之后的main方法的其他代码的运行就与run方法运行无关了 以当前代码为例
- t0.start()的之后的main方法的其他代码与run方法的代码并行运行 就像两条河流一样,各走各的
- 那么控制台输出的结果就是两条并行程序的运行结果总和,这个结果需要拆开成两部分看 就可以看到,各自是保持自己输出顺序
- 这个就是多线程的异步,这个异步相对于执行t0.start()的主程序来说的
- 简单来说开启了线程之后run方法中运行的代码主程序中t0.start()之后的程序是并行执行的,没先后关系,这个叫异步
通过实现Runnable接口方式实现多线程
public class TestRunnable implements Runnable{
int count = 0;
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + ":Runnable多线程运行的代码");
for(int i = 0; i < 5; i++){
count++;
System.out.println(Thread.currentThread().getName() + ":这是Runnable多线程的逻辑代码:" + count);
}
}
}
-------------------------------
public class Test {
public static void main(String[] args) {
Thread t3 = new Thread(new TestRunnable());
t3.start();
Runnable run = new TestRunnable();
Thread t4 = new Thread(run, "t-1");
t4.start();
Thread t5 = new Thread(run, "t-2");
t5.start();
}
}
区别:Thread与Runnable
- 继承Thread:线程代码存放Thread子类run方法中。重写run方法
- 实现Runnable:线程代码存在接口的子类的run方法。实现run方法
- 实现方法的好处
- 避免了单继承的局限性
- 多个线程可以共享同一个接口实现类的对象,非常适合,多个线程可以用来处理同一份资源
- 一般使用实现接口方式来实现多线程
package day15;
public class Test1 {
public static void main(String[] args) {
TestRun run0 = new TestRun();
TestRun run1 = new TestRun();
Thread t0 = new Thread(run0);
Thread t1 = new Thread(run1);
t0.setName("线程t-0");
t1.setName("线程t-1");
t0.setPriority(1);
t1.setPriority(10);
t0.start();
t1.start();
System.out.println("---------------1");
System.out.println("---------------2");
System.out.println(t1.isAlive());
t1.stop();
try {
t0.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("---------------3");
System.out.println(t1.isAlive());
}
}
class TestRun implements Runnable {
int count = 0;
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + ":Runnable多线程运行的代码");
for (int i = 0; i < 5; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (i % 2 == 0) {
Thread.yield();
}
count++;
System.out.println(Thread.currentThread().getName() + ":这是Runnable多线程的逻辑代码:" + count);
}
}
}
微信与支付宝支付案例
package day15;
public class Test2 {
public static void main(String[] args) {
Acount a = new Acount();
Acount a1 = new Acount();
User u_weixin = new User(a, 2000);
User u_zhifubao = new User(a, 2000);
Thread weixin = new Thread(u_weixin,"微信");
Thread zhifubao = new Thread(u_zhifubao,"支付宝");
weixin.start();
zhifubao.start();
}
}
class Acount{
public static int money = 3000;
public synchronized void drawing(int m){
String name = Thread.currentThread().getName();
if(money < m){
System.out.println(name + "操作,账户金额不足:" + money);
}else{
System.out.println(name + "操作,账户原有金额:" + money);
System.out.println(name + "操作,取款金额:" + m);
System.out.println(name + "操作,取款操作:原金额" + money + " - " + "取款金额" + m);
money = money - m;
System.out.println(name + "操作,取款后的余额:" + money);
}
}
public synchronized void drawing1(int m){
String name = Thread.currentThread().getName();
if(money < m){
System.out.println(name + "操作,账户金额不足:" + money);
}else{
System.out.println(name + "操作,账户原有金额:" + money);
System.out.println(name + "操作,取款金额:" + m);
System.out.println(name + "操作,取款操作:原金额" + money + " - " + "取款金额" + m);
money = money - m;
System.out.println(name + "操作,取款后的余额:" + money);
}
}
public static synchronized void drawing2(int m){
String name = Thread.currentThread().getName();
if(money < m){
System.out.println(name + "操作,账户金额不足:" + money);
}else{
System.out.println(name + "操作,账户原有金额:" + money);
System.out.println(name + "操作,取款金额:" + m);
System.out.println(name + "操作,取款操作:原金额" + money + " - " + "取款金额" + m);
money = money - m;
System.out.println(name + "操作,取款后的余额:" + money);
}
}
public void drawing3(int m){
synchronized(this){
String name = Thread.currentThread().getName();
if(money < m){
System.out.println(name + "操作,账户金额不足:" + money);
}else{
System.out.println(name + "操作,账户原有金额:" + money);
System.out.println(name + "操作,取款金额:" + m);
System.out.println(name + "操作,取款操作:原金额" + money + " - " + "取款金额" + m);
money = money - m;
System.out.println(name + "操作,取款后的余额:" + money);
}
}
}
public void drawing4(int m){
synchronized(this){
String name = Thread.currentThread().getName();
if(money < m){
System.out.println(name + "操作,账户金额不足:" + money);
}else{
System.out.println(name + "操作,账户原有金额:" + money);
System.out.println(name + "操作,取款金额:" + m);
System.out.println(name + "操作,取款操作:原金额" + money + " - " + "取款金额" + m);
money = money - m;
System.out.println(name + "操作,取款后的余额:" + money);
}
}
}
public void drawing5(int m,Acount a){
synchronized(a){
String name = Thread.currentThread().getName();
if(name.equals("微信")){
try {
a.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if(money < m){
System.out.println(name + "操作,账户金额不足:" + money);
}else{
System.out.println(name + "操作,账户原有金额:" + money);
System.out.println(name + "操作,取款金额:" + m);
System.out.println(name + "操作,取款操作:原金额" + money + " - " + "取款金额" + m);
money = money - m;
System.out.println(name + "操作,取款后的余额:" + money);
}
if(name.equals("支付宝")){
try {
a.notify();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
class User implements Runnable{
Acount acount;
int money;
public User(Acount acount,int money){
this.acount = acount;
this.money = money;
}
@Override
public void run() {
acount.drawing5(money, acount);
}
}
经典生产者消费者问题
package day15;
public class Test3 {
public static void main(String[] args) {
Clerk c = new Clerk();
new Thread(new Runnable() {
@Override
public void run() {
synchronized (c) {
while (true) {
if (c.productNum == 0) {
System.out.println("产品数为0,开始生产");
while (c.productNum < 4) {
c.productNum++;
System.out.println("库存:" + c.productNum);
}
System.out.println("产品数为" + c.productNum + ",结束生产");
c.notify();
} else {
try {
c.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}, "生产者").start();
new Thread(new Runnable() {
@Override
public void run() {
synchronized (c) {
while (true) {
if (c.productNum == 4) {
System.out.println("产品数为4,开始消费");
while (c.productNum > 0) {
c.productNum--;
System.out.println("库存:" + c.productNum);
}
System.out.println("产品数为" + c.productNum + ",结束消费");
c.notify();
} else {
try {
c.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}, "消费者").start();
}
}
class Clerk {
public static int productNum = 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律