进程和线程的区别&&创建多线程详解&&start()方法和run()方法的区别&&静态代理模式

线程概述

  •  进程 线程
  •  进程 线程概念

     1、进程:操作系统 调度程序 动态概念

     2、在进程内多条执行路径

            .一个进程可拥有多个并行的线程

            .一个进程中的线程共享相同的内存单元/内存地址空间、可以访问相同的变量和对象,而且它们从同一堆中分配对象、通信、数据交换、同步操作

            .由于线程间的通信是在同一地址空间上进行的,所以不需要额外的通信机制,这就是得通信更简便而且信息传递的速度也更快。

        (多个线程执行一个结果时就会出现并发情况)

 

  • 线程和进程的区别

区别

进程

线程

根本区别

作为资源分配的单位

调度和执行的单位

开销

每个进程都有独立的代码和数据空间,进程间的切换会有较大的开销。

线程可以看成轻量级的进程,同一类线程共享代码和数据空间,每个线程有独立的运行栈和程序计数器(pc),线程切换的开销小。

所处环境

在操作系统中能同时运行多个任务(程序)

在同一应用程序中有多个顺序流同时执行

分配内存

系统在运行的时候会为每个进程分配不同的内存区域

除了CPU之外,不会为线程分配内存

包含关系

没有线程的进程是可以被看作单线程的,如果一个进程内拥有多个线程,则执行过程不是一条线的,而是多条线程共同完成的。

线程是进程的一部分,所以线程有的时候被称为是轻量级进程

  • 了解完多线程之后先弄懂这两种发法区别

start()和run()的区别?

start():

用start方法来启动线程,真正实现了多线程运行,这时无需等待run方法代码执行完直接继续执行下面的代码。通过调用Thread

类的start()方法来启动一个线程,这时此线程处于就绪(可运行)状态,并没有运行,一但得到cpu时间片,就开始执行run()方法,这里方法run()称为线程体,它包含了要执行的这个线程的内容,run()方法运行结束,此线程随即终止。

run():

run()方法只是类的一个普通方法而已,如果直接调用run()方法,程序中依然只有主线程这一个线程,其程序执行路径还是只有一条,还是要顺序执行,还是要等待run()方法体执行完毕后才可继续执行下面的代码,这样就没有达到写线程的目的。

总结:

调用start()方法可启动线程,而run()方法只是Thread的一个普通方法调用,还是在主线程里执行。这两个方法应该都比较熟悉,把需要并行处理的代码放在run()方法中,start()方法启动线程将自动调用run()方法,这是由jvm的内存机制规定的。并且run()方法必须是public访问权限,返回值类型为void。

一、线程创建之继承Thread类

package com.aozhi.thread;

/**
 *这种方式的缺点:那就是如果我们的类已经从一个类继承,则无法再继承Thread类。
 * 模拟赛车比赛
 * 创建多线程继承thread类实现run()方法
 * @author songhaibo
 *
 * 2019年7月11日-下午3:05:54
 */
public class TestThread {
	public static void main(String[] args) {
		Racing rc = new Racing();
		Ferrari fa = new Ferrari();
		rc.start();
		fa.start();
		//rc.run();
		//fa.run();
		for (int i = 0; i < 50; i++) {
			System.out.println("main--->" + i);
		}
	}
}

class Racing extends Thread {
	@Override
	public void run() {
		for (int i = 0; i < 50; i++) {
			System.out.println("GTR跑了" + i + "英里");
		}
	}
}

class Ferrari extends Thread {
	@Override
	public void run() {
		for (int i = 0; i < 50; i++) {
			System.out.println("Ferrari跑了" + i + "英里");
		}
	}
}

 

二、线程创建之一实现Runnable接口

package com.aozhi.thread;

/**
 * 使用静态代理模式
 * 实现接口便于共享资源
 * @author songhaibo
 *
 * 2019年7月11日-下午5:01:17
 */
public class TestRunnable {

	public static void main(String[] args) {
		//Runnable实现类对象,真实角色
		Thread1 role1 = new Thread1();
		//线程类代理角色,该类也实现了Runnable接口,代理角色
		Thread thread1 = new Thread(role1);//传入了真实角色的引用
		thread1.start();
	}
}

class Thread1 implements Runnable {
	@Override
	public void run() {
		//TODO
	}

}
  • 在这里实现Runnable接口用到了设计模式里的静态代理模式,首先我们来看一下静态代理模式

参考文章:https://www.cnblogs.com/yxiaooutlook/p/7798563.html

package com.aozhi.thread;

/**
 * 静态代理模式
 * 要求:真实角色,代理角色;真实角色和代理角色要实现同一个接口,代理角色要持有真实角色的引用。
 * 
 *在Java中线程的设计就使用了静态代理设计模式,其中自定义线程类实现Runable接口,
 *Thread类也实现了Runalbe接口,在创建子线程的时候,传入了自定义线程类的引用,
 *再通过调用start()方法,调用自定义线程对象的run()方法。实现了线程的并发执行。
 *
 * @author songhaibo
 *
 * 2019年7月11日-下午4:17:22
 */
public class Staticproxy {
	public static void main(String[] args) {
		//创建真实角色对象
		Proxy realityRole = new RealityRole();
		//创建代理角色对象,并制定真实对象
		ProxyRole proxyRole = new ProxyRole(realityRole);
		//代理角色工作,本质调用的还是真实角色的功能
		proxyRole.run();
	}
}

/*
 * 共同的接口
 */
interface Proxy {
	public abstract void run();
}

//真实角色
class RealityRole implements Proxy {

	@Override
	public void run() {
		System.out.println("run");
	}
}

//
class ProxyRole implements Proxy {
	// 持有代理角色的引用
	private Proxy realityRole;

	//传入一个真实角色
	public ProxyRole(Proxy role) {
		realityRole = role;
	}

	@Override
	public void run() {
		//在真实角色功能运行之前,代理角色做准备工作
		doBefore();
		//执行真实角色的功能
		realityRole.run();
		//代理角色的收尾工作
		doAfter();

	}

	private void doBefore() {
		System.out.println("准备工作");
	}

	private void doAfter() {
		System.out.println("收尾工作");
	}

}

三、实现Callable接口

这种方式主要就是针对前两种都是实现run()方法,但是run()方法没有返回值,这种方式就是可以抛异常有返回值。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值