标签:Runnable run Thread 创建 start 线程 多线程
多线程
基本概念:程序、进程、线程
- 程序(program)是为了完成特定任务、用某种语言编写地一组指令的集合。即指一段静态的代码,静态对象。
- 进程(process)是程序的依次执行过程,或是正在运行的一个程序。是一个动态的工程:有它自身的产生、存在和消亡的过程。-----生命周期
- 程序是静态的,进程是动态的
- 进程作为资源分配的单位,系统在运行时会为每个进程分配不同的内存区域
- 线程(thread),进程可进一步细化为线程,是一个程序内部的一条执行路径。
- 若一个进程同一时间并行执行多个线程,就是支持多线程的
- 线程作为调度和执行的单位,每个线程拥有独立的运行栈和程序计数器(pc),线程切换的开销小
- 一个进程中的多个线程共享相同的内存单元/内存地址空间->它们从同一堆中分配对象,可以访问相同的遍历狼和对象。这就使得线程间通信更简便、高效。但多个线程操作共享的系统资源可能就会带来安全隐患。
- 一个Java应用程序java.exe,其实至少有三个线程:main()主线程,gc()垃圾回收线程,异常处理线程。如果发生异常,会影响主线程。
- 并行与并发
- 并行:多个CPU同时执行多个任务。比如:多个人同时做不同的事。
- 并发:一个CPU(采用时间片)同时执行多个任务。比如:秒杀、多个人做同一件事。
- 多线程的创建,方式一:继承于Thread类
- 创建一个继承于Thread类的子类
- 重写Thread类的run()-->将此线程执行的操作声明在run()中
- 创建Thread类的子类的对象
- 通过此对象调用start()
//例:遍历100以内的所有的偶数
//1.创建一个继承于Thread类的子类
class Mythread extends Thread{
//2.重写Thread类的run()
@Override
public void run() {
for (int i = 0; i < 100; i++) {
if (i%2==0){
System.out.println(Thread.currentThread().getName()+":"+i);
}
}
}
}
public class ThreadTest {
public static void main(String[] args) {
//3.创建Thread类的子类的对象
Mythread t1 = new Mythread();
//4.通过此对象调用start():4.1启动当前线程 4.2调用当前线程的run()
//问题一:我们不能通过直接调用run()的方式启动线程
// t1.run();
t1.start();
//问题二:再启动一个线程遍历100内的偶数,错误,不可以还让已经start()的线程去执行。会报IllegalThreadStateException异常
//我们需要重新创建一个线程的对象
// t1.start();
Mythread t2 = new Mythread();
t2.start();
//创建Thread匿名子类的方式
new Thread(){
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("匿名子类方式");
}
}
}.start();
//如下操作在main方法中执行
for (int i = 0; i < 100; i++) {
if (i%2!=0){
System.out.println(Thread.currentThread().getName()+":"+i);
}
}
}
}
-
Thread中常用方法:
- start():启动当前线程;调用当前线程的run()
- run():通常需要重写Thread类中的此方法,将创建的线程要执行的操作声明在此方法中
- currentThread():静态方法,返回执行当前代码的线程
- getName():获取当前线程的名字
- setName():设置当前线程的名字
- yield():释放当前cpu的执行权
- join():在线程a中调用线程b的join(),此时线程啊就进入阻塞状态,直到线程b完全执行完以后,线程a才结束阻塞状态
- stop():已过时,当执行完此方法时,强制结束当前线程
- sleep(long millitime):让当前线程“睡眠”指定的millitime毫秒。在指定的millitime毫秒时间内,当前线程时阻塞状态。
- isAlive():判断当前线程是否还存活
-
线程的调度
- 调度策略
- 时间片
- 抢占式:高优先级的线程抢占CPU
- Java的调度方法
- 同优先级线程组成先进先出队列(先到先服务),使用时间片策略
- 对高优先级,使用有限调度的抢占式策略
- 线程的优先级等级
- MAX_PRIORITY:10
- MIN_PRIORITY:1
- NORM_PRIORITY:5
- 涉及的方法:
- getPriority():返回线程优先值
- setPriority(int newPriority):改变线程的优先级
- 说明:
- 线程创建时继承父线程的优先级
- 低优先级只是获得调度的概率低,并非一定是在高优先级线程之后才被调用
- 高优先级的线程要抢占低优先级线程cpu的执行权。但是只是从概率上讲,高优先级的线程高概率的抢矿下被执行。并不意味着只有当高优先级的线程执行完以后,低优先级的线程才执行。
- 调度策略
-
创建多线程的方式二:实现Runnable接口
- 创建一个实现了Runnable接口的类
- 实现类去实现Runnable中的抽象方法:run()
- 创建实现类的对象
- 将此对象作为参数传递到Thread类的构造器中,创建Thread类的对象
- 通过Thread类的对象调用start()
/*
* 创建多线程的方式二:实现Runnable接口
1. 创建一个实现了Runnable接口的类
2. 实现类去实现Runnable中的抽象方法:run()
3. 创建实现类的对象
4. 将此对象作为参数传递到Thread类的构造器中,创建Thread类的对象
5. 通过Thread类的对象调用start()
*/
//1.创建一个实现了Runnable接口的类
class MThread implements Runnable{
//实现类去实现Runnable中的抽象方法:run()
@Override
public void run() {
for (int i = 0; i < 100; i++) {
if(i % 2 == 0){
System.out.println(Thread.currentThread().getName()+":"+i);
}
}
}
}
public class ThreadTest1 {
public static void main(String[] args) {
//3.创建实现类的对象
MThread mThread = new MThread();
//4.将此对象传入到Thread类的构造中,创建Thread的对象
Thread thread = new Thread(mThread);
//5.通过Thread类的对象调用start 5.1 启动线程 5.2 调用当前线程的run--->调用了Runnable类型的target的run方法
thread.setName("线程一");
thread.start();
//再启动一个线程,遍历100以内的偶数
Thread t2 = new Thread(mThread);
t2.setName("线程二");
t2.start();
}
}
- 比较创建线程的两种方式:
- 开发中:优先选择:实现Runnable接口的方式
- 原因:1.实现的方式没有类的单继承性的局限性 2.实现的方式更适合来处理多个线程有共享数据的情况
- 联系:public class Thread implements Runnable
- 相同点:两种方式都需要重写run(),将线程要执行的逻辑声明在run()中。
标签:Runnable,run,Thread,创建,start,线程,多线程 来源: https://www.cnblogs.com/rhy2103/p/16271000.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。