Java多线程-------线程创建的三种方式

创建线程的三种方式

  1. 继承Thread类,重写run方法
  2. 实现Runnable接口
  3. 实现callable接口

 

 

一、继承Thread类

 

main方法 :主线程   

main方法里面定义的线程:子线程

 

举一个例子演示一下,主线程和子线程抢占执行的例子

先看自己定义的thread类,是一个子线程,循环运行100次

再看看主函数,注意主函数里面启动子线程需要使用start()方法,不是run方法,然后主线程也循环运行50次

查看运行结果:说明线程之间是抢占式执行


引出下一个问题的背景,当我们又创建了一个线程,也是Mythread的线程,当我们执行主函数的时候,就有三个线程在运行了,但是Thread1和Thread2运行的是同一个for循环,我们怎么知道是哪一个线程运行出来的结果呢?所以我们就需要获取线程的ID和线程的名称

 

一:获取线程的ID和名称的方法:System.out.println("线程id:"+this.getId()+"线程名称:"+this.getName()+"子线程。。。。。。。"+i);  第一种只在继承Thread线程下才可以用,实现runnable接口就不适用了

推荐使用第二种方式更普遍:或者使用方法获取:System.out.println("线程ID"+Thread.currentThread().getId()+"线程名称"+Thread.currentThread().getName()+"子线程........");

 

为线程取名字:我们就介绍一种方法:使用有参构造函数创建

在主函数中传过来的名字,交给Thread父类的方法执行命名操作

 

实例一

使用继承Thread类实现4个窗口各卖一百张票,每个窗口都有100张票

 

 

 

二、实现Runnable接口

注意这里需要说明一下,创建一个runnable接口,表示线程要执行的功能,表示线程要执行的功能,表示线程要执行的功能。认真读这句话

之前我们第一种创建线程的方式,是通过线程启动的方式运行的。而现在我们需要把我们写好的功能交给线程对象

这里线程正好提供了一个runnable接口的方法

 

代码:

运行结果也是抢占式的执行

补充,想到接口就请联想到匿名内部类,我们可以使用它来简化代码

简化上面的代码,我们直接new一个接口,我们都是知道,接口是不能实例化的,但是我们可以通过匿名内部类,相当于给接口创建一个子类,我们并没有写出来,所以就叫做匿名。

 

实例二

实现4个窗口共卖100张票

 

由于票数是共享的,所以我们就应该想到卖票的操作也是共享的,共有的

所以:我们将Ticket这个类实现runnbale接口,都共同重写run方法,所以我们将卖票操作写到run方法

核心代码是创建线程,将ticket传给了Thread。注意我们主函数这里只创建一个票对象,创建四个线程对象。

运行结果:出现争夺问题,这个问题留到后面再解决

现在回来解决这个问题,出现这个问题的原因是线程之间互相争抢资源,出现了不确定的结果,所以我们需要增加锁的机制

代码修改如下

运行测试:

或者代码不用创建锁,直接使用当前对象

 

示例二

 

我们这个例子:我们发现 银行卡是共享的,所以先创建这么一个卡的类

我们只关心余额,所以只创建一个变量

然后我们不能在card的类里面实现runnable接口,因为我们要实现两个不同的功能,所以我们需要创建两个类分别实现runnable接口,实现不同的功能

红框框里面代表的是实现了构造方法

测试

 

或者这样写:注意JDK版本需要是1.8,1.7运行不行,编译都过不了

package Tesr;

public class TestCard2 {
	public static void main(String[] args) {
		Card card = new Card();
		Runnable addRunnable = new Runnable() {
			//Card card = new Card();
			@Override
			public void run() {
				// 存钱功能
				for (int i = 0; i < 12; i++) {
					card.setBalance(card.getBalance()+1000);
					System.out.println(Thread.currentThread().getName()+"存了1000元,余额为:"+card.getBalance());
				}
				
			}
		};
		
		Runnable subRunnable = new Runnable() {
			//Card card = new Card();
			@Override
			public void run() {
				for (int i = 0; i < 12; i++) {
					if(card.getBalance()>=1000) {
						card.setBalance(card.getBalance()-1000);
						System.out.println(Thread.currentThread().getName()+"取了1000,余额为: "+card.getBalance());
					}else {
						System.out.println("余额不足");
						i--;//保证能取到钱
					}
				}
				
			}
		};
		new Thread(addRunnable,"明明").start();
		new Thread(subRunnable,"bingbing").start();
		
		
	}
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

你在狗叫什么、

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值