多线程
前言
本文主要浅Java基础中的多线程
提示:以下是本篇文章正文内容,下面案例可供参考
一、概念
1.1什么是进程?
> 独立运行的应用程序叫进程
什么是应用程序,就是咱们打开各个软件,比如 谷歌浏览器,360,qq音乐等这些软件,他们都是独立的一个运行起来的软件,叫应用应用程序,
代码里面写过Demo1 Demo2这些类,也可以叫一个应用程序,也可以叫进程
进程需要通过系统的分配,获取系统中的cpu,内存,显卡,网络等。
独立性 :qq和谷歌浏览器没有关系的,他们之间是独立的
互斥性:咱们软件的运行都是在抢占cpu,谁抢过谁先执行。
直到为什么有的时候一个软件会卡,让你等待。是因为这个软件在抢占cpu
的时候,没有抢占过别的软件。所以要么关闭软件,等待响应。
1.2什么是线程?
进程是有多个线程组成的,而且一个进程至少得有一个线程
线程是进程的灵魂所在,看不见摸不着。进程可以看到,就是正在运行的应用程序,但是内存是怎么运行的呢,其实是线程在运行的
线程是组成进程的最小单位。
如果把一个人比作一个进程,那么细胞就是一个线程
线程具有什么特性:
1.抢占式运行: CPU执行应用程序的时候是按照时间片执行的,而且单位时间内时间片被线程相互抢占式的运行
例子:卫生间就三个位置,一个班级有100个人,抢占这个位置,谁抢到谁就先用。等你释放以后,其他人再抢,线程很忙,不断的抢占CPU的执行权,不断的释放。
2.资源共享性:
一个线程可以共享当前资源,cpu、内存
QQ这个进程,假如占用的运行内存为3MB,QQ内的多个线程可以共同去抢占这3MB的运行内存。
进程之间能资源共享吗?线程之间能资源共享吗?
进程之间不能资源共享 IDEA和QQ这是两个进程,不可以共享资源
线程之间可以共享资源,在一个应用程序中,抢占同一个资源
一个JAVA应用程序至少有几个线程?
2个线程:一个为main主函数线程,另外一个为JVM垃圾回收线程。
1.3进程和线程的区别?
进程是一个完整的应用程序,而且一个线程至少有一个线程,可以把进程看做一个生产车间。线程是进程的一个执行的功能,可以看做一个生产车间内的一条生产线。
一个生产车间是有多条生产线组成的,一个应用程序是有多个线程组成的。
进程申请的是Windows系统的资源
线程申请的是进程内的资源。
多个线程在执行的时候,cpu会根据每个线程分配时间片来随机轮流执行。
每个线程最多占用的时间片大概是20ms,过了这个时间片就切换到另外一个线程了。
将卫生间比作一个应用程序,一个进程
在这个进程中,有100个(学生)线程,去申请这个卫生间的资源,这个卫生间的资源有3MB(三个坑位)。每个学生去抢占这个坑位,只给你留的时间片大概为20ms。保证这个进程一直在执行,没有挂掉,视觉感觉不到线程在在抢占资源,感觉到的是应用程序一直在执行。
1.4并发和并行
并发:同时发生,轮流交替执行
并行:真正意义的同时执行
举个例子:
比如你点了两盘菜,最终你都要将这两盘菜吃完,。
从老板的角度有来看。属于同时吃完的。但是严格意义上来讲,轮流交替吃的。属于并发。
并行:比如你和你同桌两个人,一人点了一个菜,你吃你的我吃我的,并行
1.5线程的优缺点
优点:
1.提高资源的利用率,cpu不至于空闲
2.电脑可以执行多个功能
3.提升用户的体验
缺点:
1.加重了cpu 的负担
2.降低cpu执行其它线程的概率,可能会导致线程的卡顿
3.共享资源的问题
4.会产生死锁
二、创建线程的两种方式
2.1方式一:继承Thread类
方式一:
①自定义线程类去继承Thread类,重写run方法
②在main主函数中创建自定义线程类的实例,然后调用start()方法启动线程。
代码示例如下:
//1.自定义线程类去继承Thread类
class MyThread2 extends Thread{
//2.重写run()方法
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("我是MyThread2里面的线程");
}
}
}
public class Demo4 {
public static void main(String[] args) {
//3.创建自定义的线程类的对象
MyThread2 myThread2 = new MyThread2();
//4.通过自定义的线程类的对象调用start()方法
myThread2.start();
//start()方法的作用:①启动当前线程②调用当前线程的run()方法。
for (int i = 0; i < 100; i++) {
System.out.println("我是main主线程");
}
}
}
2.2方式二、实现Runnable接口
方式二:
① 自定义线程类,去实现Runnable接口,重写run()方法
②在main主函数中 实例化自定义的线程类,将实例化的对象作为参数传递给Thread的带参构造方法,创建Thread类的对象
③通过Thread类的对象调用start()方法,启动线程。
代码示例如下:
//1.自定义线程类去实现Runnable接口
class MyThread3 implements Runnable{
//2.重写run()方法
//将该线程要执行的功能写在run()方法内
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("我是MyThread3的线程");
}
}
}
public class Demo5 {
public static void main(String[] args) {
//3.实例化自定义线程类的对象
MyThread3 myThread3 = new MyThread3();
//4.将自定义线程类的对象作为参数传递给Thread类的带参构造方法
//创建Thread类的对象
Thread thread = new Thread(myThread3);
//5.通过Thread类的对象调用start()
thread.start();
//start():①启动当前线程②调用当前线程的run()
for (int i = 0; i < 100; i++) {
System.out.println("我是main主线程");
}
}
}
三、线程类常用的方法
构造方法:
Thread();//创建了一个线程对象
Thread(Runnable target);//创建线程对象,传入的是Runnable接口的实现类
Thread(Runnable target,String name);//创建线程对象,传入的是Runnable接口的实现类,和当前线程的名字
成员方法:
static Thread currentThread();//获取当前线程的对象
void setName(String name);//设置当前线程的名字
String getName();//获取当前线程的名字
void setPriority(int newPriority);//设置当前线程的优先级
优先级只能增加线程的执行概率,不一定优先,线程的默认优先级为5,取值范围为1-10,优先级最高的为10
int getPriority();//获取当前线程的优先级
static void sleep(long millis);//让当前线成进行休眠,传入的是一个long类型的数据(毫秒数)
代码示例如下:
class MyThread5 implements Runnable{
@Override
public void run() {
//获取当前线程对象
Thread thread = Thread.currentThread();
//获取当前线程的优先级
System.out.println(thread.getPriority());//5
System.out.println(thread.getName());//通过当前的线程对象获取线程的名字
for (int i = 0; i < 100; i++) {
System.out.println(thread.getName() + " :"+i);
}
}
}
class MyThread6 implements Runnable{
@Override
public void run() {
Thread thread = Thread.currentThrea