JAVA 最难学的部分是哪里?很多朋友都会说:「 java 多线程 」。
随着业务量和数据的增加,企业不可避免地会使用多线程的方式处理数据。在 Java 职位的面试中,多线程也是必考的高阶知识点之一。可以说,java多线程是衡量一名 Java 程序员是否资深的关键标准之一。
今天,我们就来学习一下 Java 多线程的概念吧!
(点击课程链接,开启实验环境,边学边练才是更有效的学习方式)Java 多线程技术实战www.shiyanlou.com
多进程与多线程的概念
初步创建多线程,理清多线程的概念。
知识点多线程的概念
创建多线程 —— 继承 Thread
创建多线程 —— 实现 Runnable
创建多线程 —— 实现 Callable
多进程和多线程的概念进程是程序在计算机上的一次执行活动。当你运行一个程序,你就启动了一个进程。凡是用于完成操作系统的各种功能的进程就是系统进程,而所有由你启动的进程都是用户进程。
多进程
进程是程序在计算机上的一次执行活动。当你运行一个程序,你就启动了一个进程。凡是用于完成操作系统的各种功能的进程就是系统进程,而所有由你启动的进程都是用户进程。
如图所示每一个正在运行的 .exe 程序都是一个进程。
多线程
进程就是有一个或多个线程构成的。而线程是进程中的实际运行单位,是独立运行于进程之中的子任务。是操作系统进行运算调度的最小单位。可理解为线程是进程中的一个最小运行单元。
进程和线程之间的关系
一个进程下包含 N 个线程。举例说明:玩英雄联盟的时候,打开客户端便启动了许多个线程:排队队列线程、好友聊天线程、正在支付线程。在英雄联盟这一个进程之下便启动了 N 个线程。
我们初学 java 边写代码的时候,通常使用 main 方法进行运行,此时 main 方法执行的便是一个主线程,而所谓的多线程,即是在主线程执行的过程中,同时执行其他的线程。但是同时执行多个线程容易出现报错现象,例如同时同分同秒,两个线程同时修改一个 txt、数据库表文件,或第一个线程没有修改完 txt、数据库表文件,第二个线程同时也去修改。这便是线程之间的混乱、资源竞争、脏读,便是程序员需要去解决的疑难杂症。
创建多线程 —— 继承 Thread
java 世界中有两种方式创建多线程:
java 世界中有两种方式创建多线程,分别是继承 Thread 类,实现 Runnable 接口。
继承 Thread 类方式创建多线程
第一步:在 webide 上右键单击菜单,选择 New File 创建新文件。
第二步:创建文件名为 test0.java
第三步:编写 test0.java 中继承 Thread 类方式创建多线程的代码如下所示:
public class test0 {
public static void main(String[] args) {
Thread MyThread = new MyThread();
MyThread.start();
}
}
class MyThread extends Thread {
@Override
public void run() {
System.out.println("hello myThread" + Thread.currentThread().getName());
}
}
第四步:编译 test0.java 代码:
javac test0.java
编译之后,会产生我们所编写的 test0 类与 MyThread 类
第五步:运行 test 代码:java test0
创建多线程 —— 实现 Runnable
只需要把《创建多线程 —— 继承 Thread》中代码修改成如下所示即可,其它操作不变:
public class test0 {
public static void main(String[] args) {
MyRunnable myRunnable = new MyRunnable();
Thread thread = new Thread(myRunnable);
thread.start();
}
}
class MyRunnable implements Runnable{
@Override
public void run(){
System.out.println("hello myRunnable" + Thread.currentThread().getName());
}
}
执行结果如下所示:通常情况下,如果创建的线程类已经含有父类时候,此时由于 Java 语法结构不支持多继承的原因,不能够再次继承 Thread 类,此时则需要使用实现 Runnable 接口的方式来应对如此场景。另外值得说明的是,Thread 类也实现了 Runnable 接口。
实现多线程传参 —— 有参构造
由于多线程是由继承 Thread 或实现 Runnable 并重写 run() 方法,通过 thread.start() 进行运行的,而本身重写的 run() 方法是不具备传参能力的,那我新建的线程就接受不到我所想传入的参数了么?
创建 study1.java 文件
class ThreadA extends Thread{
private String age;
public ThreadA(String age){
this.age = age;
}
@Override
public void run() {
System.out.println("age=" + age);
}
}
public class study1 {
public static void main(String[] args) {
String age = new String("12");
ThreadA a = new ThreadA(age);
a.start();
}
}
无论 extendsThread 还是 implementsRunnable ,传参都需要使用线程初始化的有参构造形式,达到多线程传参的目的。也可以做到重载有参构造,传入各式对象。
study1 运行结果
实现多线程返回值 —— 实现 Callable
通常意义上理解确实 Java 实现多线程的方式有继承 Thread 和实现 Runnable,但是如果想实现多线程并且具有返回值的情况下,需要实现 Callable 接口,这个接口是 JDK1.5 版本以后才出现的接口。
创建 study2.java
创建 study2.java 文件,利用实现 Callable 进行返回,代码如下所示:
import java.util.concurrent.Callable;
public class study2 {
public static void main(String[] args) {
MyCallable MyCallable = new MyCallable("张方兴");
String call = null;
try {
call = MyCallable.call();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(call);
}
}
class MyCallable implements Callable{
private String name;
public MyCallable(String name) {
this.name = name;
}
@Override
public String call() throws Exception {
return "call:" + name;
}
}
study2 运行结果
Callable 接口详解
一般继承 Thread 的类,含有 .start() 函数,所以直接可以使用 .start() 函数进行启动。实现 Runnable 的类,需要通过 newThread(myRunnable).start(); 的方式进行启动,即实现 Runnable 的类只是做好了一段多线程所需执行的内容,自身并没有执行的能力,需要通过 Thread 类的 .start() 函数进行启动。实现 Callable 的接口,含有 .call() 函数,所以可以直接使用 .call() 函数进行启动,另外值得说明的是, Callable 函数具有返回值,返回值为定义类时使用的 类型,其定义是其返回。 Callable 接口定义如下所示:
@FunctionalInterface
public interface Callable {
/*** Computes a result, or throws an exception if unable to do so.** @return computed result* @throws Exception if unable to compute a result*/
V call() throws Exception;
}
Callable 用于指示接口类型声明是由 Java 语言规范定义的功能接口。从概念上讲,函数接口只有一个抽象方法。因为 java.lang.reflect.Method#isDefault()default methods 有一个实现,所以它们不是抽象的。如果接口声明一个抽象方法重写 java.lang.Object 的一个公共方法,则该方法也不计入接口的抽象方法计数,因为接口的任何实现都将具有来自 java.lang.Object 或其他位置的实现。另外注意,函数接口的实例可以使用 lambda 表达式、方法引用或构造函数引用创建。Callable 在需要使用返回值的情况下,程序是同步运行的Callable 。其它情况下,程序是异步运行的
完整课程内容,请在实验楼边操作边学习。Java 多线程技术实战www.shiyanlou.com