栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

多线程基础

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

多线程基础

多线程基础

Java.Thread

多线程概述

线程简介

任务、进程、线程、多线程

线程实现(重点)

线程状态

线程同步(重点)

线程通信问题

高级主题

线程、进程、多线程 线程

多任务

现实中太多这样同时做多件事情的例子了,看起来是多个任务都在做,其实本质上我们 的大脑在同一时间依旧只做了一件事情。

多线程

多线程例子(生活,游戏,编程)

原来是一条路,慢慢因为车太多了,道路堵塞,效率极低。 为了提高使用的效率,能够充分利用道路,于是加了多个车道。

并发

普通方法调用和多线程

在操作系统中运行的程序就是进程,比如你的 QQ,播放器,游戏,IDE等

声音 字幕 图像 进程

一个进程可以有多个线程,如视频中同时听声音,看图像,看弹幕等

process与thread

说起进程,就不得不说下程序。程序是指令和数据的有序集合,其本身没有任何运行的含义,是一个静态的概念。

而进程则是执行程序的一次执行过程,它是一个动态的概念。是系统资源分配的单位

通常在一个进程中可以包含若干个线程,当然一个进程中至少有一个线程,不然没有存在的意义。线程是CPU调度和执行的的单位。

注意:

很多多线程是模拟出来的,真正的多线程是指有多个cpu,即多核,如服务器。

如果是模拟出来的多线程,即在一个cpu的情况下,在同一个时间点,cpu只能执行一个代码,因为切换的很快,所以就有同时执行的错局。

本章核心概念 :

线程就是独立的执行路径;在程序运行时,即使没有自己创建线程,后台也会有多个线程,如主线程,gc线程;main() 称之为主线程,为系统的入口,用于执行整个程序;在一个进程中,如果开辟了多个线程,线程的运行由调度器安排调度,调度器是与 操作系统紧密相关的,先后顺序是不能认为的干预的。对同一份资源操作时,会存在资源抢夺的问题,需要加入并发控制;线程会带来额外的开销,如cpu调度时间,并发控制开销。每个线程在自己的工作内存交互,内存控制不当会造成数据不一致。 继承Thread类 线程创建

Thread 、Runnable、Callable

三种创建方式

Thread class => 继承Thread类(重点)

Runnable接口 => 实现Runnable接口(重点)

Callable接口 => 实现Callable接口(了解)

Thread

学习一个类,首先查看JDK帮助文档

自定义线程类继承Thread类重写run()方法,编写线程执行体创建线程对象,调用start()方法启动线程

public class StartThread extends Thread{
    //线程入口点
    @override
    public void run(){
        //线程体
        for (int i = 0;i < 20;i++){
            System.out.println("我在学习多线程---");
        }
    }
}

线程不一定立即执行,CPU安排调度

public static void main(String[] args){
    //创建线程对象
    StartThread t = new StartThread();
    t.start();
}
package com.feng.demo;



public class TestThread1 extends Thread {

    @Override
    public void run() {
        //run方法线程体
        for (int i = 0; i < 20; i++) {
            System.out.println("我在学习多线程---"+i);
        }
    }

    public static void main(String[] args) {
        //main线程,主线程

        //创建一个线程对象
        TestThread1 testThread1 = new TestThread1();

        //调用start开启线程
        testThread1.start();

        for (int i = 0; i < 20; i++) {
            System.out.println("我在敲代码---"+i);
        }
    }
}
//总结:线程开启不一定立即执行,由CPU调度执行
网图下载

范例:下载图片

引入:Commons IO包,工具类库

new package,命名为lib百度搜索Commons IO,拷贝到项目lib里面。add as library

//文件下载工具类
class WebDownloader{
    //远程路径,存储名字
    public void downloader(String url,String name){
        try{
            //Commons IO是针对开发IO流功能的工具类库
            //FileUtils文件工具,复制url到文件
            FileUtils.copyURLToFile(new URL(url),new File(name));
        }catch(IOException e){
            e.printStackTrace();
            System.out.println("文件下载失败");
        }
    }
}
@Override
public void run(){
    WebDownloader webDownloader = new WebDownloader();
    webDownloader.downloader(url,name);
    System.out.println(name);
}
public static void main(String[] args){
    StartThread2 t1 = new StartThread2;
    StartThread2 t2 = new StartThread2;
    StartThread2 t3 = new StartThread2;
    
    //启动三个线程
    t1.start();
    t2.start();
    t3.start();
    
}
package com.feng.demo;

import org.apache.commons.io.FileUtils;

import java.io.File;
import java.io.IOException;
import java.net.URL;

//练习Thread,实现多线程同步下载图片
public class TestThread2 extends Thread{

    private String url;  //网络图片地址
    private String name;  //保存的文件名

    public TestThread2(String url,String name){
        this.url = url;
        this.name = name;

    }
    //下载图片线程的执行体
    @Override
    public void run(){
        WebDownloader webDownloader = new WebDownloader();
        webDownloader.downloader(url,name);
        System.out.println("下载了文件名为:"+name);

    }

    public static void main(String[] args) {
        TestThread2 t1 = new TestThread2("https://img9.51tietu.net/pic/2019-091301/v1e3d2do0dsv1e3d2do0ds.jpg","1.jpg");
        TestThread2 t2 = new TestThread2("https://img9.51tietu.net/pic/2019-091301/v1e3d2do0dsv1e3d2do0ds.jpg","2.jpg");
        TestThread2 t3 = new TestThread2("https://img9.51tietu.net/pic/2019-091301/v1e3d2do0dsv1e3d2do0ds.jpg","3.jpg");

        //线程同时执行的
        t1.start();
        t2.start();
        t3.start();

    }
}

//下载器
class WebDownloader{
    //下载方法
    public void downloader(String url,String name){
        try {
            FileUtils.copyURLToFile(new URL(url), new File(name));
        }catch(IOException e){
            e.printStackTrace();
            System.out.println("IO异常,downloader方法出现问题");
        }
    }
}
//找不到或无法加载主类,save all再试一试
实现Runnable接口

查看JDK帮助文档

定义MyRunnable类实现Runnable接口实现run()方法,编写线程执行体创建线程对象,调用start()方法启动线程

public class StartThread3 implements Runnable{
    @Override
    public void run(){
        //线程体
        for(int i = 0;i < 20;i++){
            System.out.println("我在学习多线程---");
        }
    }
}
//创建实现类对象
StartThread3 st = new StartThread3();
//创建代理类对象
Thread thread = new Thread(st);
//启动
thread.start();

推荐使用Runnable对象,因为Java单继承的局限性

小结

继承Thread类

子类继承Thread类具备多线程能力启动线程:子类对象.start()不建议使用:避免OOP单继承局限性 实现Runnable接口

实现接口Runnable具有多线程能力启动线程:传入目标对象+thread对象.start()推荐使用:避免单继承局限性,灵活方便,方便同一个对象被多个线程使用

//一份资源
StartThread startion = new StartThread();
//多个代理
new Thread(station,name:"小黎").start();
new Thread(station,name:"小海").start();
new Thread(station,name:"小桃").start();
package com.feng.demo;



public class TestThread3 implements Runnable{
    @Override
    public void run(){
        //run方法线程体
        for (int i = 0; i < 20; i++) {
            System.out.println("我在学习多线程---"+i);

        }
    }

    public static void main(String[] args) {
        //创建Runnable接口的实现类对象
        TestThread3 testThread3 = new TestThread3();

        //创建线程对象,通过线程对象来开启我们的线程,代理
        Thread thread = new Thread(testThread3);
        thread.start();
        
        //new Thread(testThread3).start();

        for (int i = 0; i < 20; i++) {
            System.out.println("我在敲代码---"+i);

        }

    }
}

初识并发问题
package com.feng.demo;

//多个线程同时操作同一个对象
//买火车票的例子

//发现问题,多个线程同时操作同一个资源的情况下,线程不安全,数据混乱

public class TestThread4 implements Runnable{

    //票数
    private int ticketNums = 10;

    @Override
    public void run(){
        while(true){
            if(ticketNums <= 0){
                break;
            }

            //模拟延时
            try {
                Thread.sleep(200);
            }catch(InterruptedException e){
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+"-->拿到了第" +ticketNums--+"票");
            //ticketNums--
        }
    }

    public static void main(String[] args) {

        TestThread4 ticket = new TestThread4();

        new Thread(ticket,"小黎").start();
        new Thread(ticket,"小海").start();
        new Thread(ticket,"小桃").start();
        //点一点ticket "" 就会出现 name:

    }
}
龟兔赛跑-race
    首先来个赛道距离,然后要离终点越来越近判断比赛是否结束打印出胜利者龟兔赛跑开始故事中是乌龟赢的,兔子需要睡觉,所以我们来模拟兔子睡觉终于,乌龟赢得比赛
package com.feng.demo;

//模拟龟兔赛跑
public class RaceThread5 implements Runnable{

    //胜利者
    private static String winner;

    @Override
    public void run(){
        for (int i = 0; i <= 100; i++) {

            //模拟兔子休息
            if(Thread.currentThread().getName().equals("兔子")&& i%10==0){
                try {
                    Thread.sleep(100);
                }catch(InterruptedException e){
                    e.printStackTrace();
                }

            }

            //判断比赛是否结束
            boolean flag = gameOver(i);
            //如果比赛结束了就停止
            if(flag){
                break;
            }
            System.out.println(Thread.currentThread().getName()+"-->跑了"+i+"步");
        }
    }


    //判断是否完成比赛
    private boolean gameOver(int steps){
        //判断是否有胜利者
        if(winner!=null) {  //已经存在胜利者了
            return true;
        }{
            if(steps==100){
                winner = Thread.currentThread().getName();
                System.out.println("winner is"+winner);
                return true;
            }
        }
        return false;
    }

    public static void main(String[] args) {
        RaceThread5 raceThread5 = new RaceThread5();

        new Thread(raceThread5,"兔子").start();
        new Thread(raceThread5,"乌龟").start();

    }
}
实现Callable接口 静态代理模式 Lamda表达式 线程停止 线程休眠_sleep 线程礼让_yield 线程强制执行_join 观测线程状态 线程的优先级 守护线程 线程同步机制 三大不安全案例 同步方法及同步块 CopyonWriteArrayList 死锁 Lock锁 生产者消费者问题 管程法 信号灯法 线程池 总结
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/781797.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号