大数据必学Java基础(七十六):创建线程的三种方式
【摘要】 创建线程的三种方式一、继承Thread类在学习多线程之前,以前的代码是单线程的吗?不是,以前也是有三个线程同时执行的。;现在我想自己制造多线程 --》 创建线程 ?线程类 --》 线程对象;package com.lanson.test01;/** * @author : Lansonli * 线程类叫:TestThread,不是说你名字中带线程单词你就具备多线程能力了(争抢资源能力) * ...
创建线程的三种方式
一、继承Thread类
在学习多线程之前,以前的代码是单线程的吗?
不是,以前也是有三个线程同时执行的。
;
现在我想自己制造多线程 --》 创建线程 ?
线程类 --》 线程对象
;
package com.lanson.test01;
/**
* @author : Lansonli
* 线程类叫:TestThread,不是说你名字中带线程单词你就具备多线程能力了(争抢资源能力)
* 现在想要具备能力,继承一个类:Thread,具备了争抢资源的能力
*/
public class TestThread extends Thread{
/*
一会线程对象就要开始争抢资源了,这个线程要执行的任务到底是啥?这个任务你要放在方法中
但是这个方法不能是随便写的一个方法,必须是重写Thread类中的run方法
然后线程的任务/逻辑写在run方法中
*/
@Override
public void run() {
//输出1-10
for (int i = 1; i <= 10 ; i++) {
System.out.println(i);
}
}
}
package com.lanson.test01;
/**
* @author : Lansonli
* 测试类
*/
public class Test {
//这是main方法,程序的入口
public static void main(String[] args) {
//主线程中也要输出十个数:
for (int i = 1; i <= 10 ; i++) {
System.out.println("main1-----"+i);
}
//制造其他线程,要跟主线程争抢资源:
//具体的线程对象:子线程
TestThread tt = new TestThread();
//tt.run();//调用run方法,想要执行线程中的任务 -->这个run方法不能直接调用,直接调用就会被当做一个普通方法
//想要tt子线程真正起作用比如要启动线程:
tt.start();//start()是Thread类中的方法
//主线程中也要输出十个数:
for (int i = 1; i <= 10 ; i++) {
System.out.println("main2-----"+i);
}
}
}
运行结果:
;
设置读取线程名字
1、setName,getName方法来进行设置读取
package com.lanson.test01;
/**
* @author : Lansonli
* 线程类叫:TestThread,不是说你名字中带线程单词你就具备多线程能力了(争抢资源能力)
* 现在想要具备能力,继承一个类:Thread,具备了争抢资源的能力
*/
public class TestThread extends Thread{
/*
一会线程对象就要开始争抢资源了,这个线程要执行的任务到底是啥?这个任务你要放在方法中
但是这个方法不能是随便写的一个方法,必须是重写Thread类中的run方法
然后线程的任务/逻辑写在run方法中
*/
@Override
public void run() {
//输出1-10
for (int i = 1; i <= 10 ; i++) {
System.out.println(this.getName()+i);
}
}
}
package com.lanson.test01;
/**
* @author : Lansonli
* 测试类
*/
public class Test {
//这是main方法,程序的入口
public static void main(String[] args) {
//给main方法这个主线程设置名字:
//Thread.currentThread()作用获取当前正在执行的线程
Thread.currentThread().setName("主线程");
//主线程中也要输出十个数:
for (int i = 1; i <= 10 ; i++) {
System.out.println(Thread.currentThread().getName()+"1-------"+i);
}
//制造其他线程,要跟主线程争抢资源:
//具体的线程对象:子线程
TestThread tt = new TestThread();
tt.setName("子线程");
//tt.run();//调用run方法,想要执行线程中的任务 -->这个run方法不能直接调用,直接调用就会被当做一个普通方法
//想要tt子线程真正起作用比如要启动线程:
tt.start();//start()是Thread类中的方法
//主线程中也要输出十个数:
for (int i = 1; i <= 10 ; i++) {
System.out.println(Thread.currentThread().getName()+"2-------"+i);
}
}
}
2、通过构造器设置名字
package com.lanson.test01;
/**
* @author : Lansonli
* 线程类叫:TestThread,不是说你名字中带线程单词你就具备多线程能力了(争抢资源能力)
* 现在想要具备能力,继承一个类:Thread,具备了争抢资源的能力
*/
public class TestThread extends Thread{
public TestThread(String name){
super(name);//调用父类的有参构造器
}
/*
一会线程对象就要开始争抢资源了,这个线程要执行的任务到底是啥?这个任务你要放在方法中
但是这个方法不能是随便写的一个方法,必须是重写Thread类中的run方法
然后线程的任务/逻辑写在run方法中
*/
@Override
public void run() {
//输出1-10
for (int i = 1; i <= 10 ; i++) {
System.out.println(this.getName()+i);
}
}
}
习题:买火车票
1、原理:每个窗口都是一个线程对象
;
2、代码
package com.lanson.test02;
/**
* @author : Lansonli
*/
public class BuyTicketThread extends Thread {
public BuyTicketThread(String name){
super(name);
}
//一共10张票:
static int ticketNum = 10;//多个对象共享10张票
//每个窗口都是一个线程对象:每个对象执行的代码放入run方法中
@Override
public void run() {
//每个窗口后面有100个人在抢票:
for (int i = 1; i <= 100 ; i++) {
if(ticketNum > 0){//对票数进行判断,票数大于零我们才抢票
System.out.println("我在"+this.getName()+"买到了从北京到哈尔滨的第" + ticketNum-- + "张车票");
}
}
}
}
package com.lanson.test02;
/**
* @author : Lansonli
*/
public class Test {
public static void main(String[] args) {
//多个窗口抢票:三个窗口三个线程对象:
BuyTicketThread t1 = new BuyTicketThread("窗口1");
t1.start();
BuyTicketThread t2 = new BuyTicketThread("窗口2");
t2.start();
BuyTicketThread t3 = new BuyTicketThread("窗口3");
t3.start();
}
}
二、实现Runnable接口
代码:
package com.lanson.test03;
/**
* @author : Lansonli
* TestThread实现了这个接口,才会变成一个线程类
*/
public class TestThread implements Runnable{
@Override
public void run() {
//输出1-10数字:
for (int i = 1; i <= 10 ; i++) {
System.out.println(Thread.currentThread().getName()+"----"+i);
}
}
}
package com.lanson.test03;
/**
* @author : Lansonli
*/
public class Test {
public static void main(String[] args) {
//创建子线程对象:
TestThread tt = new TestThread();
Thread t = new Thread(tt,"子线程");
t.start();
//主线程里面也是打印1-10数字:
for (int i = 1; i <= 10 ; i++) {
System.out.println(Thread.currentThread().getName()+"---"+i);
}
}
}
运行结果:
;
习题:买火车票
代码
package com.lanson.test04;
/**
* @author : Lansonli
*/
public class BuyTicketThread implements Runnable {
int ticketNum = 10;
@Override
public void run() {
for (int i = 1; i <= 100 ; i++) {
if(ticketNum > 0){
System.out.println("我在"+Thread.currentThread().getName()+"买到了北京到哈尔滨的第" + ticketNum-- + "张车票");
}
}
}
}
package com.lanson.test04;
/**
* @author : Lansonli
*/
public class Test {
//这是main方法,程序的入口
public static void main(String[] args) {
//定义一个线程对象:
BuyTicketThread t = new BuyTicketThread();
//窗口1买票:
Thread t1 = new Thread(t,"窗口1");
t1.start();
//窗口2买票:
Thread t2 = new Thread(t,"窗口2");
t2.start();
//窗口3买票:
Thread t3 = new Thread(t,"窗口3");
t3.start();
}
}
实际开发中,方式1 继承Thread类 还是 方式2 实现Runnable接口这种方式多呢?
方式2
- 方式1的话有 Java单继承的局限性,因为继承了Thread类,就不能再继承其它的类了
- 方式2的共享资源的能力也会强一些,不需要非得加个static来修饰
Thread类 Runnable接口 有联系吗?
;
三、实现Callable接口
对比第一种和第二种创建线程的方式发现,无论第一种继承Thread类的方式还是第二种实现Runnable接口的方式,都需要有一个run方法, 但是这个run方法有不足:
;
- 没有返回值
- 不能抛出异常
基于上面的两个不足,在JDK1.5以后出现了第三种创建线程的方式:
实现Callable接口
实现Callable接口好处:
(1)有返回值
(2)能抛出异常
缺点:线程创建比较麻烦
package com.lanson.test05;
import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
/**
* @author : Lansonli
*/
public class TestRandomNum implements Callable<Integer> {
/*
1.实现Callable接口,可以不带泛型,如果不带泛型,那么call方式的返回值就是Object类型
2.如果带泛型,那么call的返回值就是泛型对应的类型
3.从call方法看到:方法有返回值,可以跑出异常
*/
@Override
public Integer call() throws Exception {s
return new Random().nextInt(10);//返回10以内的随机数
}
}
class Test{
//这是main方法,程序的入口
public static void main(String[] args) throws ExecutionException, InterruptedException {
//定义一个线程对象:
TestRandomNum trn = new TestRandomNum();
FutureTask ft = new FutureTask(trn);
Thread t = new Thread(ft);
t.start();
//获取线程得到的返回值:
Object obj = ft.get();
System.out.println(obj);
}
}
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)