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接口的方式来实现多线程。

原文地址:https://www.cnblogs.com/jnba/p/10563117.html

时间: 2024-10-02 22:35:30

java并发编程基础——线程的创建的相关文章

Java并发编程:线程的创建

.title { text-align: center } .todo { font-family: monospace; color: red } .done { color: green } .tag { background-color: #eee; font-family: monospace; padding: 2px; font-size: 80%; font-weight: normal } .timestamp { color: #bebebe } .timestamp-kwd

Java并发编程:线程的同步

.title { text-align: center } .todo { font-family: monospace; color: red } .done { color: green } .tag { background-color: #eee; font-family: monospace; padding: 2px; font-size: 80%; font-weight: normal } .timestamp { color: #bebebe } .timestamp-kwd

【转】Java并发编程:线程池的使用

Java并发编程:线程池的使用 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程就会大大降低系统的效率,因为频繁创建线程和销毁线程需要时间. 那么有没有一种办法使得线程可以复用,就是执行完一个任务,并不被销毁,而是可以继续执行其他的任务? 在Java中可以通过线程池来达到这样的效果.今天我们就来详细讲解一下Java的线程池,首先我们从最核心的ThreadPool

Java 并发编程:线程间的协作(wait/notify/sleep/yield/join)

Java并发编程系列[未完]: Java 并发编程:核心理论 Java并发编程:Synchronized及其实现原理 Java并发编程:Synchronized底层优化(轻量级锁.偏向锁) Java 并发编程:线程间的协作(wait/notify/sleep/yield/join) 一.线程的状态 Java中线程中状态可分为五种:New(新建状态),Runnable(就绪状态),Running(运行状态),Blocked(阻塞状态),Dead(死亡状态). New:新建状态,当线程创建完成时为新

Java并发编程:线程池的使用(转)

Java并发编程:线程池的使用 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程就会大大降低系统的效率,因为频繁创建线程和销毁线程需要时间. 那么有没有一种办法使得线程可以复用,就是执行完一个任务,并不被销毁,而是可以继续执行其他的任务? 在Java中可以通过线程池来达到这样的效果.今天我们就来详细讲解一下Java的线程池,首先我们从最核心的ThreadPool

JAVA并发编程3_线程同步之synchronized关键字

在上一篇博客里讲解了JAVA的线程的内存模型,见:JAVA并发编程2_线程安全&内存模型,接着上一篇提到的问题解决多线程共享资源的情况下的线程安全问题. 不安全线程分析 public class Test implements Runnable { private int i = 0; private int getNext() { return i++; } @Override public void run() { // synchronized while (true) { synchro

19、Java并发编程:线程间协作的两种方式:wait、notify、notifyAll和Condition

Java并发编程:线程间协作的两种方式:wait.notify.notifyAll和Condition 在前面我们将了很多关于同步的问题,然而在现实中,需要线程之间的协作.比如说最经典的生产者-消费者模型:当队列满时,生产者需要等待队列有空间才能继续往里面放入商品,而在等待的期间内,生产者必须释放对临界资源(即队列)的占用权.因为生产者如果不释放对临界资源的占用权,那么消费者就无法消费队列中的商品,就不会让队列有空间,那么生产者就会一直无限等待下去.因此,一般情况下,当队列满时,会让生产者交出对

JAVA并发编程4_线程同步之volatile关键字

上一篇博客JAVA并发编程3_线程同步之synchronized关键字中讲解了JAVA中保证线程同步的关键字synchronized,其实JAVA里面还有个较弱的同步机制volatile.volatile关键字是JAVA中的轻量级的同步机制,用来将变量的更新操作同步到其他线程.从内存可见性的角度来说,写入volatile变量相当于退出同步代码块,读取volatile变量相当于进入同步代码块. 旧的内存模型:保证读写volatile都直接发生在main memory中. 在新的内存模型下(1.5)

Java并发编程之线程创建和启动(Thread、Runnable、Callable和Future)

这一系列的文章暂不涉及Java多线程开发中的底层原理以及JMM.JVM部分的解析(将另文总结),主要关注实际编码中Java并发编程的核心知识点和应知应会部分. 说在前面,Java并发编程的实质,是线程对象调用start方法启动多线程,而线程对象则必须是Thread类或其子类实现.Runnable和Callable的作用类似于Comparable.Serializable,是用于被并发的类实现的接口,从而使得Thread类可以在初始化时传入这个被并发的类.此是大前提.本文从多线程实现和启动出发,对