进程与线程之间的关系
- 二者均可并发执行.
- 线程是指进程内的一个执行单元,也是进程内的可调度实体。一个程序至少有一个进程,一个进程至少有一个线程,一个线程只属于一个进程.
- 资源分配给进程,同一进程的所有线程共享该进程的所有资源。
- 处理机分给线程,即真正在处理机上运行的是线程。
- 线程在执行过程中,需要协作同步。不同进程的线程间要利用消息通信的办法实现同步。线程是指进程内的一个执行单元,也是进程内的可调度实体.进程和线程的主要差别在于它们是不同的操作系统资源管理方式。 进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响。而线程只是一个进程中的不同执行路径,线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间, 一个线程死掉就等于整个进程死掉,所以多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。但对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程。
- 通俗的说,进程是指运行中的程序,比如QQ,启动就可以在任务管理器中看到QQ的进程。线程由进程创建的,是进程的一个实体,一个进程至少有一个线程,可以有多个线程。线程就差不多是进程里面产生的子任务,每子任务有着各自的事情需要做
进程与线程的区别
- 根本区别 :进程是操作系统资源分配的基本单位,而线程是任务调度和执行的基本单位
- 在操作系统中能同时运行多个进程,进程中会执行多个线程
- 线程是操作系统能够进行运算调度的最小单位
并发与并行
- 并发:不同代码块交替执行
- 并行:不同代码块同时执行
线程状态
创建、就绪、运行、阻塞、死亡
创建线程的三种方式
方式一:继承Thread
继承Thread基类,重写run方法,调用start()方法启动线程
不建议使用:避免单继承局限性
/**
* 创建线程方法一:Thread
* 继承Thread基类,重写run方法
*/
public class testthread01 extends Thread{
@Override
public void run() {
for (int i=0;i<200;i++){
System.out.println("我在学习多线程---"+i);
}
}
public static void main(String[] args) {
// 创建一个线程对象
testthread01 testthread01 = new testthread01();
// 调用start()方法开启线程
testthread01.start();
}
}
方式二:实现Runnable接口
实现Runnable接口,重写run方法,创建线程对象(Thread作为代理对象),调用start()方法启动线程
推荐使用:避免Java单继承的局限性,灵活方便,方便同一个对象被多个线程使用
Runnable对象的优点 同一个对象被多个线程使用,同时也是缺点 触发多个线程操作同一个资源(同一线程对象)的情况下,线程不安全,数据撩乱
/**
* 创建线程方法二:Runnable
* 实现Runnable接口,重写run方法
* 发现问题:多个线程操作同一个资源(同一线程对象)的情况下,线程不安全,数据撩乱
*/
public class testrunnable03 implements Runnable{
public int num=10;
@Override
public void run() {
while (num>0){
// 模拟延时
try {
Thread.sleep(200);
}catch (InterruptedException e){
e.printStackTrace();
}
System.out.println("我"+Thread.currentThread().getName()+":"+num--);
}
}
public static void main(String[] args) {
testrunnable03 t1 = new testrunnable03();
new Thread(t1,"刘备").start(); //Thread 代理对象
new Thread(t1,"关羽").start();
new Thread(t1,"张飞").start();
}
}
方式三:实现Callable接口
实现Callable接口,重写call方法,有返回值
较少使用,可作为扩展学习
import java.util.concurrent.*;
/**
* 创建线程方法三:Callable
* 实现Callable接口,重写call方法,有返回值
*/
public class testcallable04 implements Callable<Boolean> {
String name;
static int num=0;
public testcallable04(String name){
this.name = name;
}
@Override
public Boolean call() {
while (num<100){
num++;
System.out.println(name+"-->"+num);
}
return true;
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
testcallable04 t1 = new testcallable04("刘备");
testcallable04 t2 = new testcallable04("关羽");
testcallable04 t3 = new testcallable04("张飞");
// 创建执行服务
ExecutorService ser = Executors.newFixedThreadPool(3);
// 提交执行
Future<Boolean> r1 = ser.submit(t1);
Future<Boolean> r2 = ser.submit(t2);
Future<Boolean> r3 = ser.submit(t3);
// 获取结果
Boolean b1 = r1.get();
Boolean b2 = r2.get();
Boolean b3 = r3.get();
// 关闭服务
ser.shutdownNow();
}
}
线程例子:龟兔赛跑
/**
* 模拟龟兔赛跑
*/
public class Race implements Runnable{
// 胜利者
private static String winner;
@Override
public void run() {
for (int i = 0; i <= 100; i++) {
if (Thread.currentThread().getName().equals("兔子")){
try{
Thread.sleep(10);
}catch(InterruptedException e){
e.printStackTrace();
}
}
if (gameover(i)){
break;
}
System.out.println(Thread.currentThread().getName()+"-->跑了"+i+"步");
}
}
public boolean gameover(int steps){
if (winner != null){
return true;
}else {
if (steps >= 100){
winner = Thread.currentThread().getName();
System.out.println("胜利者:"+winner);
return true;
}
}
return false;
}
public static void main(String[] args) {
Race race = new Race();
new Thread(race,"兔子").start();
new Thread(race,"乌龟").start();
}
}
纯属个人经验,喜欢的可以点赞关注,后续见!!!