线程的概念与创建
来源:互联网 发布:圣劳伦斯大学知乎 编辑:程序博客网 时间:2024/06/13 23:16
线程的综述
线程,有时被称为轻量级进程(Lightweight Process,LWP),是程序执行流的最小单元。一个标准的线程由线程ID,当前指令指针(PC),寄存器集合和堆栈组成。另外,线程是进程中的一个实体,是被系统独立调度和分派的基本单位,线程自己不拥有系统资源,只拥有一点儿在运行中必不可少的资源,但它可与同属一个进程的其它线程共享进程所拥有的全部资源。一个线程可以创建和撤消另一个线程,同一进程中的多个线程之间可以并发执行。由于线程之间的相互制约,致使线程在运行中呈现出间断性。线程也有就绪、阻塞和运行三种基本状态。就绪状态是指线程具备运行的所有条件,逻辑上可以运行,在等待处理机;运行状态是指线程占有处理机正在运行;阻塞状态是指线程在等待一个事件(如某个信号量),逻辑上不可执行。每一个程序都至少有一个线程,若程序只有一个线程,那就是程序本身。
线程是程序中一个单一的顺序控制流程。进程内一个相对独立的、可调度的执行单元,是系统独立调度和分派CPU的基本单位指运行中的程序的调度单位。在单个程序中同时运行多个线程完成不同的工作,称为多线程。
与进程比较:
进程是资源分配的基本单位。所有与该进程有关的资源,都被记录在进程控制块PCB中。以表示该进程拥有这些资源或正在使用它们。另外,进程也是抢占处理机的调度单位,它拥有一个完整的虚拟地址空间。当进程发生调度时,不同的进程拥有不同的虚拟地址空间,而同一进程内的不同线程共享同一地址空间。与进程相对应,线程与资源分配无关,它属于某一个进程,并与进程内的其他线程一起共享进程的资源。线程只由相关堆栈(系统栈或用户栈)寄存器和线程控制表TCB组成。寄存器可被用来存储线程内的局部变量,但不能存储其他线程的相关变量。通常在一个进程中可以包含若干个线程,它们可以利用进程所拥有的资源。在引入线程的操作系统中,通常都是把进程作为分配资源的基本单位,而把线程作为独立运行和独立调度的基本单位。由于线程比进程更小,基本上不拥有系统资源,故对它的调度所付出的开销就会小得多,能更高效的提高系统内多个程序间并发执行的程度,从而显著提高系统资源的利用率和吞吐量。
线程与进程的区别可以归纳为以下4点:
- 地址空间和其它资源(如打开文件):进程间相互独立,同一进程的各线程间共享。某进程内的线程在其它进程不可见。
- 通信:进程间通信IPC,线程间可以直接读写进程数据段(如全局变量)来进行通信——需要进程同步和互斥手段的辅助,以保证数据的一致性。
- 调度和切换:线程上下文切换比进程上下文切换要快得多。
- 在多线程OS中,进程不是一个可执行的实体。
三种创建方式
- 一、继承Tread
/** * 模拟龟兔赛跑,实现多线程方法1 * 1、创建多线程 继承Thread 需要重写run(线程体)方法 相当于程序从run()方法开始 * 2、使用线程:创建子类对象 * 3、调用对象.start方法,启动线程,自己会调用内部的run方法 * @author Administrator * */public class rabbit extends Thread{ @Override public void run() { super.run(); for(int i=0;i<100;i++){ System.out.println("兔子跑了"+i); } }}class Tortoise extends Thread{ @Override public void run() { super.run(); for(int i=0;i<100;i++){ System.out.println("乌龟跑了"+i); } }}
public class Rabbitapp { public static void main(String[] args) { //创建子类对象 rabbit r = new rabbit(); Tortoise t = new Tortoise(); //调用start方法,启动线程,自己会调用内部的run方法 r.start(); t.start(); //r.run 如果这么使用的话就会先把一个线程执行完之后,才会去执行其他的 for(int i=0;i<100;i++){ System.out.println("main-->"+i); } }}
输出结果:乌龟跑了0 乌龟跑了1 兔子跑了0 main-->0 兔子跑了1 乌龟跑了2 兔子跑了2 兔子跑了3
- 二、实现Runable接口实现多线程
/** * 继承Tread类方式实现多线程有缺点:那就是如果我们的类已经继承了一个类,比如说该类已经继承了其他小类, * 那么就无法继续继承Tread类 * 所以可以使用Runable接口实现多线程 * 优点:可以同时实现继承,避免单继承,方便共享资源,同一份资源,多个代理访问 * 静态代理 设计模式 * 1、真实角色 * 2、代理角色 * 3、二者实现相同的接口 * @author Administrator * */public class StaticProxy { public static void main(String[] args) { You you = new You(); //创建真实角色 WeddingCompany we = new WeddingCompany(you); //创建代理角色+真实角色的引用 //执行任务 we.marry(); }}//接口interface Marry{ void marry();}//真实角色class You implements Marry{ @Override public void marry() { System.out.println("结婚了"); }}//代理角色-->持有真实角色的引用class WeddingCompany implements Marry{ private Marry you; public WeddingCompany() { } public WeddingCompany(Marry you) { super(); this.you = you; } private void before(){ System.out.println("准备新房"); } private void after(){ System.out.println("入洞房"); } @Override public void marry() { before(); you.marry(); after(); }}
下面就利用runnable实现多继承:
public class Video { public static void main(String[] args) { //创建真实角色 ChatQQ c = new ChatQQ(); //创建代理角色 Thread t = new Thread(c); //调用.stat,启动线程 t.start(); for(int i=0;i<20;i++){ System.out.println("在看"+i+"集电视剧!"); } }}class ChatQQ implements Runnable{ @Override public void run() { for(int i=0;i<20;i++){ System.out.println("和"+i+"个人在聊QQ!"); } }}
public class Web12306 implements Runnable { private int num = 50;//1到50号 @Override public void run(){ while(true) { if(num <= 0){ break;//跳出循环 } System.out.println(Thread.currentThread().getName() + "抢到了" + num--); } } public static void main(String[] args) { //真实角色 Web12306 web = new Web12306(); //代理 Thread t1 = new Thread(web, "路人甲"); Thread t2 = new Thread(web, "黄牛乙"); Thread t3 = new Thread(web, "攻城狮"); t1.start(); t2.start(); t3.start(); }}
- 三、实现Callable接口
优点:可以获取返回值
Callable和Future接口
Callable是类似于Runnable的接口,实现Callable接口的类和实现Runnable接口的类都是可被其它线程执行的任务
Callable和Runnable有几点不同:
1、Callable规定的方法是call(),而Runnable规定的方法是run()
2、call()方法可抛出异常,而run()方法不能抛出异常
3、Callable的任务执行后可返回值,运行Callable任务可得到一个Future对象,而Runnable的任务不能返回值
Future表示异步计算的结果。它提供了检查计算是否完成的方法,以等待计算的完成,并检索计算的结果。通过Future对象可了解任务执行情况,可取消任务的执行,还可获取任务执行的结果。
缺点:繁琐
思路:
1)创建:Callable实现类 +重写call
2)借助:执行调度服务ExecutorService,获取Future对象
ExecutorService ser = Executors.newFixedThreadPool(2);
Future result = ser.submit(实现类对象)
3)获取值:result.get()
4)停止服务:ser.shutdownNow();
import java.util.concurrent.Callable;import java.util.concurrent.ExecutionException;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.Future;public class Test_Callable { public static void main(String[] args) throws InterruptedException, ExecutionException { //创建线程 ExecutorService ser = Executors.newFixedThreadPool(2);//2个线程 Race gui = new Race("乌龟",1000); Race tutu = new Race("小兔子",100); //获取值 Future<Integer> result1 = ser.submit(gui); Future<Integer> result2 = ser.submit(tutu); Thread.sleep(2000); gui.setFlag(false); tutu.setFlag(false); int num1 = result1.get(); int num2 = result2.get(); System.out.println("乌龟跑了-->>" + num1 + "步"); System.out.println("小兔子跑了-->>" + num2 + "步"); //停止服务 ser.shutdownNow(); }}class Race implements Callable<Integer>{ private String name; //名称 private long time; //延时 private boolean flag=true; private int step; //步数 public Race() { } public Race(String name) { super(); this.name = name; } public Race(String name, long time) { super(); this.name = name; this.time = time; } public Race(String name, long time, boolean flag, int step) { super(); this.name = name; this.time = time; this.flag = flag; this.step = step; } public String getName() { return name; } public void setName(String name) { this.name = name; } public long getTime() { return time; } public void setTime(long time) { this.time = time; } public boolean isFlag() { return flag; } public void setFlag(boolean flag) { this.flag = flag; } public int getStep() { return step; } public void setStep(int step) { this.step = step; } @Override public Integer call() throws Exception { while(flag){ Thread.sleep(time); step++; } return step; }}
- 线程的概念与创建
- Java线程的概念、创建与启动(一)
- 线程的概念及其创建
- 进程与线程的概念
- 进程与线程的概念
- 线程与进程的概念
- 线程的概念、线程与进程比较
- 多线程__【多线程的概念】【创建线程】【线程的状态】
- 线程的概念以及线程的开启和创建
- 多线程学习(一)线程概念&线程的创建
- Linux线程技术的概念与技术发展
- Linux线程技术的概念与技术发展
- Linux线程技术的概念与技术发展
- IOS中线程与进程的概念
- Linux线程技术的概念与技术发展
- 进程与线程的类比概念
- 线程与进程的概念、使用
- 进程与线程的概念和原理
- 图像增强处理之:同态滤波与Retinex算法(二)McCann Retinex和McCann99 Retinex迭代算法
- Floating Ip 绑定 qos 策略
- iOS马甲包4.3被拒后,所做的修改。结果上传成功了,分享给大家。
- .NET Core和.NET Standard有什么不同
- vue踩坑系列——vue-cli的安装
- 线程的概念与创建
- SRS性能、内存优化工具用法
- BatteryHistorian的使用
- 保护网站的图文信息不被盗取,做到这点即可
- java后端1年经验和技术总结(1)
- ARtoolkit例子中的交互代码paddleInteractionTest.c理解
- make编译时“warning: Clock skew detected. Your build may be incomplete.”解决方案
- android自APP打开高德,百度,腾讯地图APP调用
- 文章标题