创建线程的三种方式
- 继承Thread类,重写run方法
- 实现Runnable接口
- 实现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();
}
}