并发与并行
-
并发编程的目的是为了让程序运行得更快,但是,并不是启动更多的线程就能让程序最大限度地并发执行。
-
并发与并行的区别:并发是指多个线程操作同一个资源,不是同时执行,而是交替执行,单核CPU也支持多线程执行代码,CPU通过给每个线程分配CPU时间片来实现这个机制。时间片是CPU分配给各个线程的时间,因为时间片非常短,所以CPU通过不停地切换线程执行,让我们感觉多个线程是同时执行的,时间片一般是几十毫秒(ms)。(一个单间的公共厕所,有好几个人都要上厕所。但是厕所只能容纳一个人)。
并行才是真正的同时执行,多核CPU。每个线程使用一个单独的CPU的资源来运行(多间厕所只要厕所不满,进来的人都可以上厕所)

这里我们再介绍一下什么叫上下文切换:CPU通过时间片分配算法来循环执行任务,当前任务执行一个时间片后会切换到下一个任务。 但是,在切换前会保存上一个任务的状态,以便下次切换回这个任务时,可以再加载这个任务的状态。 所以任务从保存到再加载的过程就是一次上下文切换。
高并发:我们设计的程序,可以执行海量的任务同时执行
- QPS:每秒能够响应的请求数,QPS并不是并发数
- 吞吐量:单位时间内处理的请求数,QPS和并发数决定的
- 平均响应时间:系统对一个请求作出响应的平均响应时间 QPS=并发数/平均响应时间
- 并发用户数:系统可以承载的最大用户量
进程与线程
什么是进程?
进程就是一个独立运行的程序,如果一个应用程序没有被启动那么它就不是一个进程,一个进程有好多的线程。一个进程的崩溃不会影响其他的进程,例如一个游戏的崩溃不会影响QQ音乐的继续执行。

什么是线程?
线程是组成进程的基本单位,是CPU调度和分派的基本单位,他是比进程更小的能独立运行的基本单位,线程自己基本上不拥有系统资源。在运行时,只是暂用一些计数器、寄存器和栈 。
java默认有两个线程:1.主线程也就是main。2.垃圾回收器GC
如何创建一个线程
方法一、继承Thread类
class Thread implements Runnable//Thread类底层继承Runnable接口。
@Override
public void run() {
if (target != null) {
target.run();
}
}//其中的run方法是对Runnable接口run方法的具体实现
public class tries extends Thread{
@Override
public void run() {
System.out.println("多线程");
}
public static void main(String[] args) {
tries tries = new tries();
tries.start();
new Thread(tries).start();
//这种的调用方法也是可以的 tries相当于Runnable的实现类。查看jdk文档这种方式是可以的
}
}
方法二、实现Runnable接口
Runnable接口好处就是:java中不支持多继承,比如在GUI中要继承JFrame类就不能继承Thread,所以这里就可以实现Runnable接口。
public interface Runnable {
//抽象方法
public abstract void run();
}
public class tries implements Runnable{
@Override
public void run() {
System.out.println("多线程");
System.out.println("线程名:"+Thread.currentThread().getName());
}
public static void main(String[] args) {
tries tries = new tries();
new Thread(tries,"A").start();//这里第二个参数就是改变当前线程的名字
new Thread(tries).start();
}
}
方法三、实现Callable接口
public interface Callable<V> {
//用泛型来定义,该接口可以抛出异常
V call() throws Exception;
}
//继承Runnable
public interface RunnableFuture<V> extends Runnable, Future<V> {
void run();
}
public class FutureTask<V> implements RunnableFuture<V> {
//构造函数传递一个callable实列
public FutureTask(Callable<V> callable) {
if (callable == null)
throw new NullPointerException();
this.callable = callable;
this.state = NEW; // ensure visibility of callable
}
}
根据API可以看出:FutureTask类是继承Runable接口,即FutureTask是Runable接口的实现类,而FutureTask类提供了构造函数FutureTask(Callable callable),可以接受Callable类型的任务
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
public class tries implements Callable {
@Override
public Object call() throws Exception {
System.out.println("创建一个线程");
return null;
}
public static void main(String[] args) {
tries tries = new tries();
FutureTask futureTask = new FutureTask(tries);
new Thread(futureTask).start();
}
}
Runable接口和callable接口区别:
1、Callable接口规定的方法是call()方法,Runnable接口规定的方式是run()方法
2、Callable的任务执行后有返回值,而Runable的任务不能有返回值
3、call()方法可抛出异常,run()方法不能抛出异常
4、通过运行Callable的实例可以获取到FutureTask对象,FutureTask对象表示异步执行的结果,他提供了get方法可以异步获取线程执行的结果(get方法会阻塞当前线程),可以了解子线程的执行情况,可以取消任务的执行
634

被折叠的 条评论
为什么被折叠?



