线程

并发:

  • 多个不同的软件同时运行
    Windows/Linux等操作系统,同时管理多个软件并发执行
    eclipse,notepad++,chrome,各类游戏等软件同时运行
  • 一个软件可以被多个用户同时请求
    多个浏览器用户可以同时请求淘宝,同时做结算操作/支付操作
    等价于结算操作和支付操作在服务器端被多次运行
  • 总结
    多个软件同时运行
    一个软件被运行多次
    就是为了要CPU不停的工作,提高CPU的利用率

计算机是如何做到并发的:

  • 前提:一台计算机,一块CPU,一个核
  • 分析硬件CPU:
在CPU的某个时间点上只能有一个程序在执行
为了能做到并发,把CPU的时间分成若干时间片段
(时间片段的划分原则由操作系统来定义)
每个晓得时间片段只能执行一个进程
时间片到了就把程序强制离开CPU
再从内存中选出下一个程序继续执行,以此往复
看似在一段时间内十多个程序在同时运行
  • 分析软件:
	一个软件动辄几百兆或上G的内容
	一个软件是不能整个存储到内存中的额
进程:把大的软件分割成多个小的程序段,此程序段可以称之为进程
	多个大的程序要运行,先把程序分割成多个程序段
	然后把每个程序的前一部分的若干程序段加载到内存
	最终内存中放置了多个程序的多个程序段
	这些程序段要根据优先级排队
	CPU从队头获取下一个程序来运行
	大量的程序段/进程,在频繁的奇幻CPU的时候会占用CPU的时间
	做压栈和弹栈的工作,和需要部分内存存储栈中的数据

线程

因为并发会导致占用CPU的时间和内存,那么就把进程再次划分为多个更小的程序片段叫做线程
其实在CPU上来回切换的是线程,因为所有的线程共享进程的资源
在进程中包含的一个或多个线程是能够执行的独立单元

结论

CPU划片段
程序划进程段
进程段划线程段
真正在CPU上运行的是线程
尽量提高CPU的利用率
减少使用内存
进程还拥有一个私有的虚拟的内存地址,该空间仅能被他包含的线程访问,县城只能归属某一个进程,并且他只能访问该进程的所有的资源

当操作系统创建了一个进程后,该进程就会自动申请一个名为主线程或者是首要线程的线程

同类的多个线程共享一块内存空间和一组资源,县城北神有一个供程序执行的堆栈,
线程在CPU切换时负荷小,因此线程被称之为轻负荷进程,一个进程可以包含多个线程

进程和线程的区别:

一个进程至少有一个线程
线程的划分尺度小于进程,是的多个线程并发性高
另外,进程在指定的过程中,拥有独立的内存单元,而多个线程共享进程的内存空间,从而提高了程序的运行效率

线程在执行的过程中,与进程的区别在于每个独立的线程有一个程序的运行入口
顺序执行序列和程序出口,但线程不能独立运行,必须依存于进程,应用程序中由应用程序提供线程的控制

线程的应用场景:

线程通常用于一个应用程序中需要同时完成多个任务的情况
我们可以将每个任务定义一个线程,是的他们得以一同工作
也可以用于单一线程中完成,但是使用多线程可以更快的完成所需要的功能

线程的使用

在Java中能通过Java的api做线程编程操作
- 方案一:继承Thread类
			Thread类:
				此类是线程类.其每一个实例对象表示一个可以并发运行的线程
				我们可以通过继承此类并重写run方法来定义一个具体的线程
				在run方法中体现的是线程的功能(有线程的入口和出口)
				启动线程时,调用线程对象的star方法,而不是直接调用run方法
				start方法将线程纳入线程调度,使当前线程可以并发运行
				当线程获取到CPU的时间片后,可以自动运行run方法中的逻辑代码
- 方案二:实现Runnable接口
			 Runnable接口
			 	实现此接口并重写run方法来定义线程类,然后再创建线程段额时候
			 	将Runnable接口的实力传入并启动线程
				这样做的好处可以将线程和线程要执行的任务逻辑分离减少耦合
				同时Java是单继承,定义一个实现Runnable接口
				这样做可以更好的区实现其他的接口和继承父类

做线程的目的

做线程的目的实际上是为了做多线程,多线程的目的就是为了能并发
能并发的目的就是为了提高CPU的利用率

做多线程的两种方式:

  1. 多个线程共享一个run
  2. 多个线程可以每个线程一个run
  3. 前两种的组合也是多线程

Java程序员可以写线程,不需要程序员关心线程在哪个进程里

	继承Thread类
		public class MyThread extends Thread{
			public void run(){
				//线程的入口
				//线程的任务逻辑代码
				//线程的出口
			}
		}
	使用:
		MyThread mt=new MyThread();
		mt.start(0;//调用重写的run方法,实际上是多态

	实现Runnable接口
		public class RunLuoJi implements Runnable{
			public void run{
				//方法体
			}
		}
	使用:
		Thread t=new Thread(new RunLuoJi);
		t.start();//执行的是Thread中的方法
		有Thread的run方法中调用接口的run方法

线程的状态

  • 创建线程的对象 创建态 Thread t=new Thread();
  • 创建完的线程对象 就绪态 t.start();//排到线程的队列中,不一定马上获取CPU
  • 获取到CPU的资源 执行态 执行了run()方法,相当于线程出队列了
  • 执行到某一个点时有 阻塞态 从CPU上下来;//io.sleep.wait等阻塞
  • 如果正常执行完run() 结束态/消亡态 等待GC回收

线程的状态转化:

		创建态-->就绪态
		就绪态-->执行态
		执行态-->阻塞态
		  	  -->就绪态
		 	  -->结束态/消亡态
		阻塞态-->就绪态

结论:

  1. 根据业务,要考虑有多少个任务逻辑就写多少个run
  2. 每一个run要执行多少次
  3. 执行每一次run的时候,run是否使用数据,要考虑数据的安全性问题

用内部类创建线程对象

通常我们可以通过匿名内部类的方式创建线程
使用该方式可以简化编写代码的复杂度
当一个线程仅需要一个实例时
我们通常可以使用如下方式:

方式一:实现类是匿名的,对象有名
	Thread t=new Thread(){
		public void run(){
			System.out.println("run方法");
		}
	};
	t.start();

方式二:实现类是匿名的,对象也是匿名的
	new Thread(){
		public void run(){
			System.out.println("run方法");
		}
	}.start();

方式三:实现类是匿名的,对象不是匿名的,有对象名
	Runnable r=newRunnable(){
		public void run(){
			System.out.println("run方法");
		}
	};
	Thread t=new Thread(r);
	t.start();

方式四:对象时匿名的,实现类也是匿名的
	new Thread(new Runnable(){
		public void run(){
			System.out.println("run方法");
		}
	}).start();

方式五:实现类是匿名的,对象是有名的
	Thread t=new Thread(new Runnable(){
		public void run(){
			System.out.println("run方法");
		}
	});
	t.start();

创建线程对象:

1. 继承自Thread类,重写run方法
	优点:在当前的线程类中,可以回去run方法并重写,同时在当前线程类中也可以访问Thread类中的方法
	
	缺点:当前线程类不能继承其他的类,Java是单继承
	
2. 实现Runnable接口,并重写run方法
	优点:当前类可以多实现,还可以继承一次,可以吧线程对象和线程的任务逻辑代码分离出来
	
	缺点:Runnable接口的实现类只有一个run方法,想要使用其他的线程方法需要
			Thread t=new Thread(Runnable接口的实现类对象);

3. 特殊的用法,匿名内部类
	优点:写法简单,编码量少

	缺点:run的实现只有一次,且对象只有一个
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值