一、基础概念

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并发编程基础——线程的创建的更多相关文章

  1. Java并发编程:线程的创建

    Java并发编程:线程的创建 */--> code {color: #FF0000} pre.src {background-color: #002b36; color: #839496;} J ...

  2. Java并发编程基础-线程安全问题及JMM(volatile)

    什么情况下应该使用多线程 : 线程出现的目的是什么?解决进程中多任务的实时性问题?其实简单来说,也就是解决“阻塞”的问题,阻塞的意思就是程序运行到某个函数或过程后等待某些事件发生而暂时停止 CPU 占 ...

  3. java并发编程基础——线程相关的类

    线程相关类 java还为线程安全提供了一些工具类. 一.ThreadLocal类(Thread Local Variable) ThreadLocal类,是线程局部变量的意思.功用非常简单,就是为每一 ...

  4. java并发编程基础——线程池

    线程池 由于启动一个线程要与操作系统交互,所以系统启动一个新的线程的成本是比较高的.在这种情况下,使用线程池可以很好的提升性能,特别是程序中涉及创建大量生命周期很短暂的线程时. 与数据库连接池类似,线 ...

  5. java并发编程基础——线程同步

    线程同步 一.线程安全问题 如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码.如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安 ...

  6. java并发编程基础——线程通信

    线程通信 当线程在系统内运行时,程序通常无法准确的控制线程的轮换执行,但我们可以通过一些机制来保障线程的协调运行 一.传统的线程通信 传统的线程通信主要是通过Object类提供的wait(),noti ...

  7. Java并发编程基础

    Java并发编程基础 1. 并发 1.1. 什么是并发? 并发是一种能并行运行多个程序或并行运行一个程序中多个部分的能力.如果程序中一个耗时的任务能以异步或并行的方式运行,那么整个程序的吞吐量和可交互 ...

  8. 并发-Java并发编程基础

    Java并发编程基础 并发 在计算机科学中,并发是指将一个程序,算法划分为若干个逻辑组成部分,这些部分可以以任何顺序进行执行,但与最终顺序执行的结果一致.并发可以在多核操作系统上显著的提高程序运行速度 ...

  9. Java并发编程--基础进阶高级(完结)

    Java并发编程--基础进阶高级完整笔记. 这都不知道是第几次刷狂神的JUC并发编程了,从第一次的迷茫到现在比较清晰,算是个大进步了,之前JUC笔记不见了,重新做一套笔记. 参考链接:https:// ...

随机推荐

  1. Caffe框架GPU与MLU计算结果不一致请问如何调试?

    Caffe框架GPU与MLU计算结果不一致请问如何调试? 某一检测模型移植到Cambricon Caffe上时,发现无法检测出结果,于是将GPU和MLU的运行结果输出并保存后进行对比,发现二者计算结果 ...

  2. C#后台定义一个DataTable并手动写入静态数据(测试数据)

    //创建一个DataTable,并为之添加数据(自定义DataTable) DataTable dtz = new DataTable(); //添加Table中的列 DataColumn dc1 = ...

  3. Python_Selenium 之PO模式的思想、优化思路

    一.PO模式思想 PO模式是一种自动化测试设计模式,将页面定位和业务操作分开,也就是把对象的定位和测试脚本分开,从而提供可维护性. PO设计模式基础(页面作为类.元素对象作为属性.元素操作作为方法) ...

  4. springcloud-config配置异常Cannot clone or checkout repository 和 Authentication is required but no CredentialsProvider has been registered解决过程

    Cannot clone or checkout repository, 出现这个异常,通过检查是因为自己本地没有配置 ssh,所以配置了, https://blog.csdn.net/zy_2818 ...

  5. 尚硅谷Java——宋红康笔记【day11-day18】

    day11 Eclipse中的快捷键: * 1.补全代码的声明:alt + / * 2.快速修复: ctrl + 1 * 3.批量导包:ctrl + shift + o * 4.使用单行注释:ctrl ...

  6. Java8 中使用Stream 让List 转 Map使用总结

    在使用 Java 的新特性 Collectors.toMap() 将 List 转换为 Map 时存在一些不容易发现的问题,这里总结一下备查. 空指针风险 java.lang.NullPointerE ...

  7. android小技巧之点击两次退出活动

    通常在主活动中可以设置连击退出程序,下面通过代码来实现这一功能: @Override//按两次back键退出public boolean onKeyDown(int keyCode, KeyEvent ...

  8. Task06:综合练习

    练习一: 各部门工资最高的员工(难度:中等) 创建Employee 表,包含所有员工信息,每个员工有其对应的 Id, salary 和 department Id. +----+-------+--- ...

  9. 【NX二次开发】拉伸面、拉伸封闭曲线成片体UF_MODL_create_extrusion

    用那几个拉伸,不能将封闭的曲线拉伸成片体,用UF_MODL_create_extrusion函数是可以的,下面是例子. 帮助上说拉伸片体不能有拔模角度,应该是错误的,下面是一个封闭曲线带拔模角度拉伸片 ...

  10. C++中指针与引用详解

    在计算机存储数据时必须要知道三个基本要素:信息存储在何处?存储的值为多少?存储的值是什么类型?因此指针是表示信息在内存中存储地址的一类特殊变量,指针和其所指向的变量就像是一个硬币的两面.指针一直都是学 ...