1.什么是进程
是独立的运行程序
比如咱们电脑软件,你启动起来以后,他就是一个进程。qq idea
进程需要windows系统的分配。可以获取当前的系统的网卡,内存,显卡等
1.独立性
各个进程之间是相互的独立的互不影响 的。录屏软件和idea没有关系的
2.互斥性
每个软件系统都会分配一个独立端口号,如果启动一个软件以后他的端口号97。
如果再启动另外一个软件,另外一个软件如果端口也是97,这个程序就启动不了,端口被占用的
2.什么是线程
进程是由多个或者一个线程组成的。每个进程至少得有一个线程的支撑。
比方说,一个进程(qq),qq里面有很多个线程在执行。
线程的执行,撑起来了进程的执行。
把一个人比作一个进程,那么你身体里面的细胞就是线程。
进程包含了线程,线程是组成进程的最小基本单位
特性: 1.抢占式运行的【重要】 CPU在执行的时候,按照时间片来执行的,单位的时间片是抢占是执行 比如 idea qq 抢占CPU的,比如qq的线程抢到cpu,idea线程等待
比方老师是一个cpu。你们问我问题。全班同学75个线程。同时来问我问题,谁抢到,我先回答谁,其他人就需要等待。
2.资源共享性
一个线程可以共享当前CPU, 网卡等
Java程序:
一个Java程序就是一个进程 Demo1 就是一个应用程序 就是一个进程
一个Java程序Demo1里面至少 两个线程
main主函数线程
JVM垃圾回收器线程
3.线程和进程的区别【面试题】
进程是一个应用程序,是独立的
线程是进程中最小的基本单位。
把进程比作生产车间,每个流水线就是一个线程
进程有独立性和互斥性
线程有抢占式资源共享特性
4.并发和并行
并发:同时发生,轮流交替执行
并行:真正意义的同时执行
比如:
你去饭店点了两个菜,生活中拿个筷子轮流夹两个菜这就是并发场景 两盘菜,端起盘子,同时倒到嘴里面,这就是并行场景
5.创建线程的两种方式【重点】
- 一个是将一个类声明为Thread的子类。 这个子类应该重写run方法 。 然后可以分配并启动子类的实例。
package com.wyx.a_xiancheng;
class MyThread1 extends Thread{
@Override
public void run() {
//run方法中写功能代码 就是一个线程中执行的一个功能
for (int i = 0; i < 500; i++) {
System.out.println("子线程:" + i);
}
}
}
public class Demo1 {
public static void main(String[] args) {
//分配并启动子类的实例
MyThread1 myThread1 = new MyThread1();
//启动线程 开启一个线程就相当于在执行一个任务
myThread1.start();//开启线程时候会调用run这个方法
for (int i = 0; i < 500; i++) {
System.out.println("主线程:" + i);
}
//线程意义
//发现先执行了主线程,主线程还没执行完,就执行子线程,子线程还没执行完又执行了主线程
//这就是线程的抢占式运行,正因为如此,大大节省了很多时间,原先代码,是先把一个任务执行完再去执行另外一个任务,
//现在是两个任务一起执行,谁抢到先执行谁。
//就好比一个人在做饭,原先代码是先把饭做好,再去洗衣服,然后再去拖地,等待时间浪费掉
//现在是在做饭等待饭熟的同时,去洗衣服拖地。把等待时间利用起来,大大节省了时间。
}
}
另一种方法来创建一个线程是声明实现类,去实现Runnable接口。 实现类然后去实现run方法。 然后可以分配类的实例(就是创建类的实例,new对象),在创建Thread时作为参数传递,并启动。(开发用这个方法)
package com.wyx.a_xiancheng;
class MyThread2 implements Runnable {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("MyThread2" + i);
}
}
}
class MyThread3 implements Runnable{
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("MyThread3" + i);
}
}
}
public class Demo2 {
public static void main(String[] args) {
//分配类的实例
MyThread2 myThread2 = new MyThread2();
MyThread3 myThread3 = new MyThread3();
//在创建Thread时作为参数传递
Thread thread2 = new Thread(myThread2);
Thread thread3 = new Thread(myThread3);
//启动
thread2.start();
thread3.start();
for (int i = 0; i < 100; i++) {
System.out.println("主线程" + i);
}
//3个线程
//main主线程
//MyThread2
//MyThread3
//JVM垃圾回收
}
}
6.线程下面的几个方法
构造方法
Thread()分配一个新的 Thread对象。 无参构造方法 Thread(Runnable target)分配一个新的 Thread对象。 有参构造 Thread(Runnable target, String name)分配一个新的 Thread对象。并起名字
线程方法:
static Thread currentThread()返回对当前正在执行的线程对象的引用 String getName()返回此线程的名称。 void setName(String name)将此线程的名称更改为等于参数 name 。 int getPriority()返回此线程的优先级。 void setPriority(int newPriority)更改此线程的优先级。设置优先并不一定优先,只是增加了执行的概率。最小值是1,最大值是10,默认的是5 static void sleep(long millis)使当前正在执行的线程以指定的毫秒数暂停(暂时停止执行),具体取决于系统定时器和调度程序的精度和准确性。
package com.wyx.b_threadfangfa;
class MyThread1 implements Runnable{
@Override
public void run() {
Thread thread1 = Thread.currentThread();
//Thread1这个指向是MyThread1线程
System.out.println("MyThread1线程默认名字:" + thread1.getName());//MyThread1线程默认名字:Thread-0
thread1.setName("MyThread1");
System.out.println("MyThread1线程自定义名字:" + thread1.getName());//MyThread1线程自定义名字:MyThread1
}
}
class MyThread2 implements Runnable{
@Override
public void run() {
Thread thread2 = Thread.currentThread();
System.out.println("MyThread2线程自定义名字:" + thread2.getName());//MyThread2线程自定义名字:MyThread2子线程
}
}
public class Demo1 {
public static void main(String[] args) {
//启动MyThread1线程
Thread thread1 = new Thread(new MyThread1());
thread1.start();
//Thread(Runnable target, String name)分配一个新的 Thread对象。并起名字
Thread thread2 = new Thread(new MyThread2(),"MyThread2子线程");
thread2.start();
//Thread.currentThread();用来返回当前线程的引用
Thread thread = Thread.currentThread();
//Thread这个指向是main主线程
//getName();获取当前线程的名字。Jvm会给主线程还有其他线程一个默认的名字
System.out.println("主线程默认名字:" + thread.getName());//主线程默认名字:main
//setName(String name);用来给线程自定义名字
thread.setName("主线程");
System.out.println("主线程自定义的名字:" + thread.getName());//主线程自定义的名字:主线程
}
}
package com.wyx.b_threadfangfa;
class MyThread3 implements Runnable{
@Override
public void run() {
Thread thread = Thread.currentThread();
System.out.println("MyThread3子线程默认优先级:" + thread.getPriority());//5
}
}
public class Demo2 {
public static void main(String[] args) {
Thread thread3 = new Thread(new MyThread3());
thread3.start();
Thread thread = Thread.currentThread();
//getPriority():获取线程优先级
System.out.println("主线程默认优先级:" + thread.getPriority());//5
//优先级:1~10
//1优先级最低,10优先级最高
//默认线程优先级是5
//setPriority(int newPriority)更改此线程的优先级,
//设置优先并不一定优先,只是增加了执行的概率,所以一般不使用
//导致线程结果不可控。
//设置主线程优先级为1
thread.setPriority(1);
System.out.println("主线程更改之后优先级:" + thread.getPriority());
}
}
package com.wyx.b_threadfangfa;
class MyThread4 implements Runnable{
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("MyThread4:" + i);
}
}
}
class MyThread5 implements Runnable{
@Override
public void run() {
//让MyThread5先暂停一会,就意味着MyThread4先执行
try {
Thread.sleep(1000);//睡1秒
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
//重写是比较严格的。
//发现sleep只有try catch,没有抛
//public abstract void run();这是父类的run方法,发现没有抛出异常,
//又因为我们是重写的父类的run方法,所以父类没有抛出,
//我们子类重写的父类方法也不能有抛出
for (int i = 0; i < 100; i++) {
System.out.println("MyThread5:" + i);
}
}
}
public class Demo3 {
public static void main(String[] args) {
//static sleep(long millis);使当前正在执行的线程以指定的毫秒数暂停(暂时停止执行),
//具体取决于系统定时器和调度程序的精度和准确性。
//sleep这个方法在开发时候不能用,因为我们不知道当前线程需要睡多久才算合格,
//很有可能会造成cpu闲置
//睡得时间少,抢占式运行
//睡得时间长,cpu闲置
new Thread(new MyThread4()).start();
new Thread(new MyThread5()).start();
}
}