创建线程
【摘要】 进程和线程的区别联系,创建线程的几种方法
今天学完了华为云课堂java多线程实战中创建线程这一章,做一个小结,巩固新知
一、进程和线程的理解
进程和线程专业的术语我并不能记下来,但是通过自己的理解也对两者的关系和区别有了一定的认识。
首先介绍两者关系。打开任务管理器,可以看见已经启动的应用程序,每一个应用程序就是一个进程,比如qq。当我们在使用qq的某些功能如语音、视频时,我们其实就是在使用qq的线程,也就是说一个应用程序就是一个进程,而应用程序中的各个功能就是线程。进程和线程之间的关系就可以理解成父母和子女的关系,进程是父母,线程则是子女。父母可以没有子女而独立存在,而子女的存在离不开父母。
两者的区别可以从地址空间、资源拥有、执行过程三反面描述,表格如下
名称 | 进程 | 线程 |
地址空间 | 不同进程之间的地址空间独立 | 同一进程的所有线程共享本进程的地址资源 |
资源拥有 | 进程之间的资源是独立的,无法共享 | 同一进程的所有线程共享本进程的资源 |
执行过程 | 每一个进程就是一个可执行的应用程序 | 线程不能够独立执行,必须依存在应用程序中 |
二、创建线程的五种方式
1.继承Thread()类
- 通过继承Thread()类并重写run()方法,run()方法是中心方法,里面放着需要执行的任务,关键就是这个run()函数
- 创建后的子类调用start()方法就可以执行线程中的run()方法
- 注意:这种继承Thread()类创建的线程类,多个线程间无法共享线程类的实例变量
public class UserThread extends Thread{
@Override
public void run() {
for(int i = 0;i<10;i++) {
System.out.println(Thread.currentThread().getName()+"is running"+i);
//得到正在执行任务的线程的名称
}
}
}
public class UserThreadTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
Thread t1 = new UserThread();//通过继承Thread类创建的线程类,线程不共享资源
Thread t2 = new UserThread();
t1.start();
t2.start();
//两个线程同时执行任务
}
}
2.实现Runnable接口
- 先定义一个类实现Runnable接口并重写run()方法,run()是线程的执行体,是关键方法
- 创建Runnable实现类的对象
- 创建Thread()对象,将先前创建的Runnable实现类的对象作为参数传入到Thread()对象中,Thread()对象才是真正的线程对象
- 注意:利用Runnable创建的线程类对象,线程可以共享资源
public class UserRun implements Runnable{
@Override
public void run() {
// TODO Auto-generated method stub
for(int i = 0;i<10;i++) {
System.out.println(Thread.currentThread().getName()+"is Running"+i);
}
}
}
public class UserRunTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
UserRun userRun = new UserRun();
Thread t1 = new Thread(userRun);
Thread t2 = new Thread(userRun);
t1.start();
t2.start();
//两个线程同时进行
}
}
3.实现Callable接口实现带有返回值的线程
- Callable接口相当于Runnable接口的升级版,其中call()方法是执行体,和run()方法作用相同,只不过带有了返回值
- Callable对象不能作为Thread()的参数,这是和Runnable的区别,Callable接口不是Runnable接口的子接口
- 解决这个问题,引入Future接口,这个接口可以接收call()的返回值,RunnableFuture接口是Future接口和Runnable接口的子接口,可以作为Thread对象的参数
import java.util.concurrent.Callable;
public class UserCallable implements Callable{
@Override
public Object call() throws Exception {
System.out.println(Thread.currentThread().getName());
return "学习";
}
}
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
import java.util.concurrent.RunnableFuture;
public class UserCallableTest {
public static void main(String[] args) throws InterruptedException, ExecutionException {
// TODO Auto-generated method stub
UserCallable user = new UserCallable();
FutureTask ft = new FutureTask(user);//引入Future接口,可以作为Thread()的参数,Future接口可以接受call()的返回值
Thread t = new Thread(ft);
t.start();
System.out.println(ft.get());//得到call()返回值
}
}
4.继承TimerTask抽象父类
Timer和TimerTask是可以产生线程类的方法。Timer是一种线程设施,可以调度TimerTask,安排后台程序中执行的任务,任务可以执行一次或定期重复执行,相当于一个定时器
创建线程的步骤
- 定义UserTask类继承TimerTask
- 创建UserTask对象
- 创建Timer类对象,设置执行策略
import java.util.Date;
import java.util.TimerTask;
public class UserTask extends TimerTask{
@Override
public void run() {
// TODO Auto-generated method stub
System.out.println(Thread.currentThread().getName()+"is running"+new Date());
}
}
import java.util.Timer;
public class UserTaskTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
UserTask ut = new UserTask();
Timer t = new Timer();
t.schedule(ut, 2000, 1000);
}
}
三、总结
好啦,这部分就写到这了,该去吃饭了,简单来说这篇文章写了进程和线程的联系和区别以及创建线程的几种方法,重点是通过继承Thread类创建线程类和实现Runnable接口创建线程类这两种方法。收获满满,继续努力。
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)