创建线程的三种方法及并发并行的简单介绍

并发与并行

  • 并发编程的目的是为了让程序运行得更快,但是,并不是启动更多的线程就能让程序最大限度地并发执行。

  • 并发与并行的区别:并发是指多个线程操作同一个资源,不是同时执行,而是交替执行,单核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方法会阻塞当前线程),可以了解子线程的执行情况,可以取消任务的执行

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值