多线程学习——入门篇

it2024-12-16  39

前言:想成为一名优秀的程序员,线程这个重要的知识点一定要掌握。

一、什么是线程

进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。——百度百科

撇开调度不说,进程就是应用程序在内存中分配的空间,java启动main方法就是启动了一个JVM的进程,JVM内存模型如图,而main方法又是此进程中的一个线程,又称主线程。  

例:把内存比作一块地,春天了,赵家村要搞一次种地运动,村长为南区分配一块地,配置水源,工具区。张三兴致勃勃的去种地了。 如果种地任务太多,靠张三一个人速度会很慢,把张三累死了,这次运动也就失败了,因此就需要加一些人共同来种,大家每人一亩,互不影响,这样效率就高很多了。此场景中线程就是一个种地的人。

二、线程的创建与运行

1. 继承Thread类

public class ThreadDemo { public static class TillThread extends Thread { @Override public void run() { //分配任务 System.out.println("种地"); } } public static void main(String[] args) { //创建一个线程 Thread 张三 = new TillThread(); //开始执行任务 张三.start(); } }

2. 实现Runnable接口

public class ThreadDemo { public static class TillThread implements Runnable { @Override public void run() { //分配任务 System.out.println("种地"); } } public static void main(String[] args) { //创建一个任务 TillThread 种地 = new TillThread(); //创建一个线程 Thread 张三 = new Thread(种地); //开始执行任务 张三.start(); } }

3. 实现Callable类

public class ThreadDemo { public static class TillThread implements Callable<String> { @Override public String call() throws Exception { System.out.println("种地"); return "种了一亩地"; } } public static void main(String[] args) { //创建一个任务 TillThread tillThread = new TillThread(); FutureTask<String> tillTask = new FutureTask<>(tillThread); //创建一个线程 Thread 张三 = new Thread(tillTask); 张三.start(); try { String result = tillTask.get(); System.out.println(result); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } } }

这种方式可以获取到这个线程的返回值。

4. 如何选择

我们可以看到Thread也是实现的Runnable接口,考虑到java“单继承,多实现”的特性,使用实现Runnable接口的方式更加灵活。

三、常用的方法

1. 静态方法

Thread.currentThread(); ——获取正在执行的线程对象的引用。Thread.sleep(1000); ——使当前线程睡眠1秒。

2. 普通方法

thread.setName(); ——设置线程的名字。thread.getName(); ——获取线程的名字。thread.start(); ——执行线程的任务。thread.join(); ——使当前线程等待thread执行完毕后在执行。

3. 注意

多线程编程中常用的wait()和notify()是Object中的方法。

四、synchronized关键字

我们通常使用Synchronized关键字给某一段代码上锁。被上锁的代码块同一时间只能有一个线程执行。

1. 什么时候需要上锁

还是上面的例子,麦子熟了,但是南区只有一台收割机,这个时候如果张三和李四都使用那肯定是没法实现的,所以只能张三收割完李四再收割了。可以说当有资源需要排队使用时需要使用到锁。

2. 上锁的方式

Java多线程的锁都是基于对象的,Java中的每一个对象都可以作为一个锁。

// 关键字在实例方法上,锁为当前实例 public synchronized void instanceLock() { } // 关键字在静态方法上,锁为当前Class对象 public static synchronized void classLock() { } // 关键字在代码块上,锁为括号里面的对象 public void blockLock() { Object o = new Object(); synchronized (o) { } }

注:Java类只有一个Class对象(可以有多个实例对象,多个实例共享这个Class对象),而Class对象也是特殊的Java对象。所以我们常说的类锁,其实就是Class对象的锁。

2. 使用时需要注意的问题

synchronized是重量级的锁javaSE1.6后对synchronized进行了优化,所以我们放心使用。

五、思考

使用时上锁的三种方式该如何选择呢?jdk中那些地方用到了这几种方式呢?

最新回复(0)