java并发编程基础——线程的创建

Posted 技术小白丁

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java并发编程基础——线程的创建相关的知识,希望对你有一定的参考价值。

一、基础概念

1、进程和线程

进程:每个进程都有独立的代码和数据空间(进程上下文),进程间的切换会有较大的开销,一个进程包含1--n个线程。(进程是资源分配的最小单位)

线程:同一类线程共享代码和数据空间,每个线程有独立的运行栈和程序计数器(PC),线程切换开销小。(线程是cpu调度的最小单位)

2、并发性和并行性

并行:是指同一时刻,有多条指令在多个处理器上同时执行

并发:是指在同一时刻只能有一条指令执行,但多个进程指令被快速轮换执行。通常多个进程可以在当个处理器上并发执行。

3、多进程和多线程

多进程:指操作系统上同时运行多个任务

多线程:某个进程,并发处理多个任务(同一个程序中有多个程序流在执行)

 

二、线程的创建和启动

在java中要想实现多线程,有三种方式

1、继承Thread类(使用继承Thread类的方式来创建线程类时,多个线程之间无法共享线程类的实例变量)

package threadtest;
public class FirstThread extends Thread {
     
    private String name;
    public FirstThread(String name) {
        this.name = name;
    }
    public void run() {
        for(int i=0; i<10; i++) {
            System.out.println(name + ": " +i + "****"+Thread.currentThread().getName());
        }
    }
     
    public static void main(String[] args) {
        FirstThread t1 = new FirstThread("thread1");
        FirstThread t2 = new FirstThread("thread2");
        t1.start();
        t2.start();
        System.out.println(Thread.currentThread().getName());
         
    }
}

2、实现Runnable接口(使用实现Runnable接口的方式来创建线程类时,多个线程之间共享线程类的实例变量)

package threadtest;
public class SecondThread implements Runnable{
 
    private String name;
    public SecondThread(String name) {
        this.name = name;
    }
    int i=0;
    @Override
    public void run() {
        for(;i<10;i++) {
            System.out.println(name + ": "+i+"****"+Thread.currentThread().getName());
        }
    }
 
    public static void main(String[] args) {
        SecondThread st = new SecondThread("secondThread");
        Thread t1 = new Thread(st);
        Thread t2 = new Thread(st);
        Thread t3 = new Thread(st,"线程3");//可以指定线程名称
        t1.start();
        t2.start();
        t3.start();
        System.out.println(Thread.currentThread().getName());
         
    }
}

3、实现Callable接口和Future

用Callable接口创建启动多线程的步骤

(1)创建Callable接口实现类,并实现call()方法

(2)创建Callable实现类的实例,使用FutureTask类包装Callable对象

(3)使用FutureTask对象做为Thread对象的target创建并启动新的线程

(4)调用FutureTask对象的get()方法来获得子线程执行结束后的返回值

package threadtest;
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
 
public class ThirdThread implements Callable<Integer>{
 
    private String name;
    public ThirdThread(String name) {
        this.name = name ;
    }
    int i=0;
    @Override
    public Integer call() throws Exception {
        for(;i<10;i++) {
            System.out.println(name + ": " + i +"****"+ Thread.currentThread().getName());
        }
        return i;
    }
     
    public static void main(String[] args) {
         
        ThirdThread tt = new ThirdThread("thirdThread");
        FutureTask<Integer> task1 = new FutureTask<>(tt);
        FutureTask<Integer> task2 = new FutureTask<>(tt);
        FutureTask<Integer> task3 = new FutureTask<>(tt);
        Thread t1 = new Thread(task1);
        Thread t2 = new Thread(task2);
        Thread t3 = new Thread(task3,"线程3");
        t1.start();
        t2.start();
        t3.start();
        System.out.println(Thread.currentThread().getName());
         
    }
 
}

三种方式对比

通过上面三种方式都可以实现多线程,其中实现Runnable接口和实现Callable接口的方式基本相同,只是Callable接口里的方法有返回值,可以声明抛出异常。所以这两种方式可以归为一类

实现Runnable接口和实现Callable接口的方式

优势:

(1)线程类只实现了接口,还可以集成其他类

(2)多个线程可以共享一个target对象,非常适合多个线程来处理同一份资源的情况。代码和数据独立。

劣势:

(1)编程稍微复杂

继承Thread类方式

优势:

(1)编写简单

劣势:

(1)已经继承了Thread类,不能继承其他类

 

开发中一般推荐采用Runnable接口、Callable接口的方式来实现多线程。

以上是关于java并发编程基础——线程的创建的主要内容,如果未能解决你的问题,请参考以下文章

Java 并发编程 -- 并发编程线程基础(线程创建与运行线程通知与等待join / sleep / yield方法线程中断线程上下文切换死锁守护线程与用户线程ThreadLocal)

Java 并发编程 -- 并发编程线程基础(线程创建与运行线程通知与等待join / sleep / yield方法线程中断线程上下文切换死锁守护线程与用户线程ThreadLocal)

4.java并发编程艺术-java并发编程基础

Java并发编程并发基础 —— 线程

并发编程——java线程基础之线程状态转换

Java并发编程之美之并发编程线程基础