JAVA多线程部分知识点概述


提示:以下是本篇文章正文内容,下面案例可供参考

一、多线程技术概述

1.线程

  • 线程(英语:thread)是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。在Unix System V及SunOS中也被称为轻量进程(lightweight processes),但轻量进程更多指内核线程(kernel thread),而把用户线程(user thread)称为线程。《百度百科》

2.进程

  • 进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。在早期面向进程设计的计算机结构中,进程是程序的基本执行实体;在当代面向线程设计的计算机结构中,进程是线程的容器。程序是指令、数据及其组织形式的描述,进程是程序的实体。《百度百科》

3.线程与进程

  • 线程是进程的一个执行路径,共享一个内存空间,线程之间可以自由切换并发执行,一个进程最少有一个线程
  • 线程实际上是在进程基础之上的进一步划分,一个进程启动之后,里面的若干路径又可以划分成若干个线程。

4.同步与异步&并发与并行

  • 同步:排队执行,效率低但安全。
  • 异步:同时执行,效率高但是数据不安全。
  • 并发:指两个或多个事件在同一个时间段内发生。
  • 并行:指两个或多个事件在同一时刻发生(同时发生)。

5.继承Thread和实现Runnable

  • 继承Thread
public class MyThread extends Thread{
    @Override
    public void run() {
        for(int i=0;i<5;i++){
            System.out.println("Thread " + i);
        }
    }
}

public class TestDemo {
    public static void main(String[] args) {
        //实现继承Thread
        hread();
        Thread tt = new Thread(mt);
        tt.start();
    }
}
//结果
Thread 0
Thread 1
Thread 2
Thread 3
Thread 4
  • 实现Runnable
public class MyRunnable implements Runnable{
    @Override
    public void run() {
        for(int i=0;i<5;i++){
            System.out.println("Runnable"+i);
        }
    }
}

public class TestDemo {
    public static void main(String[] args) {
        //实现Runnable
        //1.    创建任务对象
        MyRunnable mr = new MyRunnable();
        //2.    创建一个线程,为其分配一个任务
        Thread t = new Thread(mr);
        //3.    执行该线程
        t.start();
    }
}
//运行结果
Runnable0
Runnable1
Runnable2
Runnable3
Runnable4

实现Runnable 相比 继承Thread有如下优势:

  1. 通过创建任务,然后给线程分配的方式来实现的多线程,更适合多个线程同时执行任务的情况。
  2. 可以避免单继承所带来的的局限性。
  3. 任务与线程本身是分离的,提高了程序的健壮性。
  4. 线程池技术接收Runnable类型的任务,不接收Thread类型的线程。

6.线程安全

  • synchronized关键字,代表这个方法加锁,相当于不管哪一个线程(例如线程A),运行到这个方法时,都要检查有没有其它线程B(或者C、
    D等)正在用这个方法(或者该类的其他同步方法),有的话要等正在使用synchronized方法的线程B(或者C
    、D)运行完这个方法后再运行此线程A,没有的话,锁定调用者,然后直接运行。它包括两种用法:synchronized 方法和synchronized 块。

  • Synchronize同步代码块
    即有synchronized关键字修饰的语句块。
    被该关键字修饰的语句块会自动被加上内置锁,从而实现同步
    代码如: synchronized(object){ }
    注:同步是一种高开销的操作,因此应该尽量减少同步的内容。
    通常没有必要同步整个方法,使用synchronized代码块同步关键代码即可。

@Override
private int count = 5;
public void run() {
    //要看同一把锁
    Object o = new Object();
    while(true){
        //买票
        synchronized (o){
            if(count>0){
                System.out.println("正在准备卖票");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                count--;
                System.out.println(Thread.currentThread().getName()+"出票成功,余票:"+count);
            }else {
                break;
            }
        }
    }
}
  • 同步方法
    即有synchronized关键字修饰的方法。 由于java的每个对象都有一个内置锁,当用此关键字修饰方法时, 内置锁会保护整个方法。在调用该方法前,需要获得内置锁,否则就处于阻塞状态。 代码如:
    public synchronized void save(){}

    注: synchronized关键字也可以修饰静态方法,此时如果调用该静态方法,将会锁住整个类

@Override
public void run() {
    while (true){
        boolean flag = sale();
        if(!flag){
            break;
        }
    }
}

public synchronized boolean sale(){
    if(count>0){
        System.out.println("正在准备卖票");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        count--;
        System.out.println(Thread.currentThread().getName()+"出票成功,余票:"+count);
        return true;
    }
        return false;
}
  • 显式锁Lock
    Lock本质上是一个接口,它定义了释放锁和获得锁的抽象方法
//创建一个锁l
public class ThreadDemo {
    public static void main(String[] args) {
        //线程不安全
        Runnable run = new Ticket();
        new Thread(run).start();
        new Thread(run).start();
    }
    static class Ticket implements Runnable{
        //票数
        private int count = 5;
        protected Object o = new Object();
        //显式锁 l  :  fair 公平锁参数为true
        private Lock l = new ReentrantLock();
        @Override
        public void run() {
            while(true){
                l.lock();
                if(count>0){
                    System.out.println("正在准备卖票");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    count--;
                    System.out.println(Thread.currentThread().getName()+"出票成功,余票:"+count);
                }else {
                    break;
                }
                l.unlock();
            }
        }
    }
}
//运行结果
正在准备卖票
Thread-0出票成功,余票:4
正在准备卖票
Thread-0出票成功,余票:3
正在准备卖票
Thread-1出票成功,余票:2
正在准备卖票
Thread-1出票成功,余票:1
正在准备卖票
Thread-1出票成功,余票:0

7.线程池

如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程就会大大降低系统的效率,因为频繁创建线程和销毁线程需要时间。线程池就是一个容纳多个线程的容器,池中的线程可以反复使用,省去了频繁创建线程对象的操作,节省了大量的时间和资源。

线程池的好处
  • 降低资源消耗.
  • 提高响应速度.
  • 提高线程的可管理性.
Java中的四种线程池:

1. 缓存线程池
(长度无限制)
执行流程:
(a)判断线程池是否存在空闲线程
(b)存在则使用
(c)不存在,则创建线程 ,并放入线程池,然后使用

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
	public class ExecutorDemo {
   	public static void main(String[] args) {
       ExecutorService service = Executors.newCachedThreadPool();
       //向线程池中加入新的任务
       service.execute(new Runnable() {
           @Override
           public void run() {
               System.out.println("线程的名称:"+Thread.currentThread().getName());
           }
       });
       service.execute(new Runnable() {
           @Override
           public void run() {
               System.out.println("线程的名称:"+Thread.currentThread().getName());
           }
       });
       service.execute(new Runnable() {
           @Override
           public void run() {
               System.out.println("线程的名称:"+Thread.currentThread().getName());
           }
       });
   }
}

//运行结果
线程的名称:pool-1-thread-2
线程的名称:pool-1-thread-1
线程的名称:pool-1-thread-3

2. 定长线程池
(长度是指定的数值)
执行流程:
(a)判断线程池是否存在空闲线程
(b)存在则使用
(c)不存在空闲线程,且线程池未满的情况下,创建线程,并放入线程池,然后使用
(d)不存在空闲线程,且线程池已满的情况下,等待线程池存在空闲线程,然后使用空闲线程

/**
* 定长线程池
*/
public class ExecutorDemo {
   public static void main(String[] args) {
   //指定长度  2
       ExecutorService service = Executors.newFixedThreadPool(2);
       service.execute(new Runnable() {
           @Override
           public void run() {
               System.out.println("线程的名称:"+Thread.currentThread().getName());
           }
       });
       service.execute(new Runnable() {
           @Override
           public void run() {
               System.out.println("线程的名称:"+Thread.currentThread().getName());
           }
       });
   }
}

3. 单线程线程池
执行流程:
(a)判断线程池是否存在空闲线程
(b)存在则使用
(c)不存在空闲线程,则等待单个线程空闲后使用

/**
* 单线程线程池 
* */
public class ExecutorDemo {
   public static void main(String[] args) {
   //指定长度  2
       ExecutorService service = Executors.newSingleThreadExecutor();
       service.execute(new Runnable() {
           @Override
           public void run() {
               System.out.println("线程的名称:"+Thread.currentThread().getName());
           }
       });
       service.execute(new Runnable() {
           @Override
           public void run() {
               System.out.println("线程的名称:"+Thread.currentThread().getName());
           }
       });
   }
}

4. 周期性任务 定长线程池
执行流程:
(a)判断线程池是否存在空闲线程
(b)存在则使用
(c)不存在空闲线程,且线程池未满的情况下,创建线程,并放入线程池,然后使用
(d)不存在空闲线程,且线程池已满的情况下,等待线程池存在空闲线程,然后使用空闲线程
周期性执行:
定时执行,当某个时机触发时,自动执行某任务.

public class ExecutorDemo {
    public static void main(String[] args) {
        ScheduledExecutorService service = Executors.newScheduledThreadPool(2);
        /**
         * 定时执行
         *  参数1.    runnable类型的任务
         *  参数2.    时长数字
         *  参数3.    市场数字的单位
         */
        service.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("两个人见面~~~  你好");
            }
        },5, TimeUnit.SECONDS);
        /**
         * 周期执行
         *  参数1.    runnable类型的任务
         *  参数2.    时长数字(延迟执行的时长)
         *  参数3.    周期时长(每次执行的间隔时间)
         *  参数4.    时长数字的单位
         */
        service.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                System.out.println("今天也要认真学习呀!!");
            }
        },5,2,TimeUnit.SECONDS);
    }
}

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

huihuisir

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值