进程和线程以及多线程
1.什么是进程?
进程:应用程序的执行实例,有独立的内存空间和系统资源,操作系统支持多进程并发运行。
线程:进程中执行运算的最小单位(对应进程某一条执行的单元),也是CPU调度和分派的基本单位,真正在CPU上运行的线程。
一个进程里可以有多个线程,我们称之为多线程。每个线程之间也是并发的。
一个线程必须有一个父的进程。
多个线程之间,我也可以让你个线程去创建和删除另外一个线程。所以,我们编程过程中,要防止线程间的相互调度
多个线程共性进程的系统资源
每一个进程都至少要有一个主线程,类似于下面代码中的main 它是程序的人口,也就是下面我定义的线程的主线程
线程之间是相互抢占资源 并发执行的
线程:系统线程 、 用户级的线程
2.如何创建一个线程
Java中创建线程的两种方式:
继承:java.lang.Thread类
实现java.lang.Runnable接口
示例如下:
MyThread类是自定的线程类,继承了Thread类
package cn.happy.thread; public class MyThread extends Thread { private int count=0; //重写Thread类的run()方法 @Override public void run() { while(count<100){ System.out.println(count); count++; } } }
下面再测试类中测试自定义的线程
package cn.happy.thread; public class MyThreadText { public static void main(String[] args) { MyThread thread1=new MyThread(); //程序员调用用start(),而不是run()方法 下面会讲解两者的区别 thread1.start(); } }
下面进行讲解第二种实现Runnable接口来自定义线程的方法,以及线程的调用
自定义的实现Runnable接口的MyThread2类
package cn.happy.thread; public class MyThread2 implements Runnable{ private int count=0; @Override public void run() { while(count<100){ System.out.println(count); count++; } } }
调用线程
package cn.happy.thread; public class MyThreadText { public static void main(String[] args) { //MyThread thread1=new MyThread(); //程序员调用用start(),而不是run()方法 下面会讲解两者的区别 //thread1.start(); //创建了一个Runnable对象,还不是一个线程 MyThread2 thread2=new MyThread2(); //做为Thread构造方法的参数传入,构建一个线程 Thread t1=new Thread(thread2); //线程启动 t1.start(); } }
上述两种方式各有优劣:
1。继承可以减少代码量
2.java中继承具有单根性,就不能再让自定义的类去继承其他的类,这时候我们就用到了实现Runnable的方式
3.使用同一个Runnable对象构造的Thread线程对象共享Runnable的资源,而Thread类不同
对上面的代码做一些修正 就会说明另外一个知识点
MyThread2
package cn.happy.thread; public class MyThread2 implements Runnable{ private int count=0; @Override public void run() { // while(count<100){ // System.out.println(count); // count++; // } count++; System.out.println(count); } }
测试类
package cn.happy.thread; public class MyThreadText { public static void main(String[] args) { //创建了一个Runnable对象,还不是一个线程 MyThread2 thread2=new MyThread2(); //做为Thread构造方法的参数传入,构建一个线程 Thread t1=new Thread(thread2); Thread t2=new Thread(thread2); //线程启动 t1.start(); t2.start(); } }
运行结果为
上述运行结果说明一个问题
我们用Runnable对象构造的Thread线程对象,多个线程如果使用同一个Runnable对象去构造的,那么他们共享Runnable对象的一些资源(j及共享了同一个count属性)
使用线程的步骤:
1.定义线程
2.创建一个线程对象
3.启动线程 用start()方法 而非run()方法
4.终止线程(1.run()执行完毕 2.在执行run()方法是发生了异常,而对于这些异常我们没有去捕获,也会强制终止进程)
start()和run()的区别
start() 1.启动了一个线程 2.调用了线程的run()
如果直接调用run(),则相当于之启动了一个普通方法。
二、线程的生命周期:
包括四个状态:新生状态、可运行状态、阻塞状态和死亡状态
阻塞:把一个线程占有的CPU资源释放出来,让线程暂停。
多个线程处于可运行状态
关于线程调度的问题,多线程并发时,我们可以控制线程的优先级(优先级越高,越有可能被执行到,也不是绝对的)
优先级:反映线程得重要或紧急程度
线程的优先级用1~10表示,1的优先级最高,默认值是5
更改优先级:
setPriority(int grade)
myThread.setPriprity(3);
线程调度的方法:
join():将指定的线程加入到当前线程
sleep():将当前线程阻塞指定的毫秒数
现在我们遇到一个问题:
当两个或多个线程需要访问同一资源时,需要确保该资源某一时刻只能被一个线程使用,该如何实现
就引出了下面的知识点
1.同步方法(synchronized)
2.同步代码块(synchronized)
线程死锁也是多线程长遇到的问题,也很难避免