多线程学习——入门篇

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

一、什么是线程

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

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

图1

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

二、线程的创建与运行

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. 使用时需要注意的问题

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

五、思考

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

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值