Java多线程

Java多线程

线程简介

多任务

通过多条道路解决多项任务:多人游戏,生活琐事,编程

多条执行路径,主线程和子线程并行交替执行

程序、进程、线程

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

Process与Thread

  • 程序:是指令和数据的有序集合,其本身并没有任何运行的含义,是一个静态的概念
  • 进程:执行程序的一次执行过程,动态概念,是系统资源分配的单位
  • 通常在一个进程中可以包含若干个线程,当然一个进程中至少有一个线程否则无意义;线程是CPU调度和执行的单位

PS:多线程大多为模拟,真实的多线程是指有多个CPU即多核,如服务器;如果是模拟出来的多线程,即在一个CPU的情况下,在同一个时间点,CPU只能执行一个代码因为切换很快所以有同时执行的错觉

###核心概念

  • main( ),称之为主线程,为系统入口用于执行整个程序

  • 一个进程中如果开辟了多个线程,线程的运行由调度器安排调度,调度器是与操作系统紧密相关的,先后顺序是不能人为干预的

  • 对同一份资源进行操作时,会存在资源争抢问题,需要加入并发控制

  • 线程会带来额外开销,如CPU调度时间,并发控制开销

  • 每个线程在自己的工作内存交互,内存控制不当会导致数据不一致

线程的创建

三种创建方式:

  • Thread class:继承Thread节点类(重点)
  • Runnable接口:实现Runnable接口(重点)
  • Callable接口:实现Callable接口

Thread

  • 自定义线程类继承Thread类
  • 重写run()方法,编写线程执行体
  • 创建线程对象,调用start()方法启用线程
//创建线程方式一:继承Thread类,重写run方法,调用start方法开启线程
public class TestThread1 extends Thread{
    @Override
    public void run(){
        //run方法线程体
        for (int i = 1;i <= 20;i++){
            System.out.println("看代码" + i);
        }
    }

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

        //创建一个线程对象
        TestThread1 testThread1 = new TestThread1();
        //调用start方法开启线程
        testThread1.start();
        for (int i = 1; i <= 100; i++) {
            System.out.println("学习多线程" + i);
        }
    }
}

/*
线程开启不一定立即执行,由CPU调度
*/

####网图下载

使用common-io.2.11.jar包

import org.apache.commons.io.FileUtils;

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

//联系Thread,实现多线程同步实现下载图片
public class TestThread2 extends Thread{//2.为实现线程类,继承Thread类变为线程类
    private String url;//网络图片地址
    private String name;//保存的文件名

    public  TestThread2(String url,String name){
        this.url = url;
        this.name = name;
    }
//3.用构造器丢入url和name,重写了线程的执行体即run方法,
    @Override
    public void run(){
        WebDownloader webDownloader = new WebDownloader();//4.调用方法
        webDownloader.downloader(url,name);
        System.out.println("下载了文件名为" + name);
    }

    public static void main(String[] args) {
        TestThread2 t1 = new TestThread2("https://p.qlogo.cn/hy_personal/3e28f14aa051684242c6be604248ad5e170822050ec983c3efd7f27026a2f2eb/0.jpg","1.jpg");
        TestThread2 t2 = new TestThread2("https://wkphoto.cdn.bcebos.com/50da81cb39dbb6fdf6c3f7401924ab18972b373f.jpg","2.jpg");
        TestThread2 t3 = new TestThread2("https://wkphoto.cdn.bcebos.com/a8014c086e061d95e31f255e6bf40ad162d9ca7f.jpg","3.jpg");

        t1.start();//5.同时启动下载图片
        t2.start();
        t3.start();
        //下载顺序为3、2、1,与代码顺序不符,表明是CPU同时执行实际为随机调度
    }
}


//1.编写下载器,通过FileUtils工具类中的copyURLToFile方法,将一个网页地址变成一个文件以保存图片
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方法出现问题");
        }
    }
}

Runnable

  • 定义MyRunnable类实现Runnable接口
  • 实现run()方法,编写线程执行体
  • 创建线程对象;传入目标对象+Thread对象.start()方法启动线程
//创建线程方式2:实现Runnable接口,重写run方法,执行线程需要丢入Runnable接口实现类,调用start方法
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);
        }
    }
}
//多线程同时操作同一个对象
//买火车票
public class TestThread4 implements Runnable{
    //票数
    private int ticketNums = 10;
    private Object object = new Object();    //声明一个对象为锁
    //多个线程同时操作时,线程数据可能出现紊乱,如重复购票和突破限制
    @Override
    public void run(){
        while (true){
            synchronized(object) {  //互斥操作,防止并发问题
                if (ticketNums <= 0) {
                    break;
                }

                //模拟延时
                try {
                    Thread.sleep(100);
                }
                catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + " get tickets NO." + ticketNums--);
                //currentThread()该方法可获得线程本身,获得当前执行线程的名称
            }
        }
    }

    public static void main(String[] args) {
        TestThread4 ticket = new TestThread4();

        new Thread(ticket,"小明").start();
        new Thread(ticket,"李华").start();
        new Thread(ticket,"坤坤").start();
    }
}
//模拟龟兔赛跑
public class Race implements Runnable{
    private static String winner;

    @Override
    public void run(){
        for (int i = 0; i <= 100; i++) {
            //模拟兔子休息
            if(Thread.currentThread().getName().equals("rabbit") && i%10==0){
                try {
                    Thread.sleep(50);
                }
                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("The winner is " + winner);
                return true;
            }
        }
        return false;
    }

    public static void main(String[] args) {
        Race race = new Race();

        new Thread(race,"rabbit").start();
        new Thread(race,"turtle").start();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值