2.线程创建(重点)

三种创建线程的方式:

  1. Thread类:继承Thread类(重点)
  2. Runnable接口:实现Runnable接口(重点)
  3. Callable接口:实现Callable接口

1.Thread类

创建线程方式一:继承Thread类;重新run方法;创建对象,调用start方法
注意:线程开启不一定立即执行,由CPU调度执行

//创建线程方式一:继承Thread类;重新run方法;创建对象,调用start方法
//注意:线程开启不一定立即执行,由CPU调度执行
public class testTread01 extends Thread {
    
    

    //线程入口点
    @Override
    public void run() {
    
    
        //线程体
        for(int i  = 0; i < 10; i ++){
    
    
            System.out.println("我在学习代码" + i);
        }
    }
}
public class Demo01 {
    
    
    //main线程,主线程
    public static void main(String[] args) {
    
    
        //创建一个线程对象
        testTread01 tt = new testTread01();
        //调用start方法开启线程
        tt.start();

        for(int i  = 0; i < 100; i ++){
    
    
            System.out.println("我在看代码" + i);
        }
    }
}

例子:下载图片

import org.apache.commons.io.FileUtils;

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

//练习thread,实现多线程同步下载图片
public class testThread02 extends Thread{
    
    
    private String url;/网络图片地址
    private String name;//保存的文件名

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

    @Override
    public void run() {
    
    
        webDownLoder wb = new webDownLoder();
        wb.downLoder(url,name);
        System.out.println("上传图片" + name);
    }

    public static void main(String[] args) {
    
    
        testThread02 tt = new testThread02("https://ss.html.cn/newimg88/2016/06/beian-gov-cn.png","1.png");
        tt.start();
    }
}
//下载器
class webDownLoder{
    
    
    //下载方法
    public void downLoder(String url,String name){
    
    

        try {
    
    
        //导入commons.io.jar包,使用其中FileUtils类中的copyURLToFile方法
            FileUtils.copyURLToFile(new URL(url),new File(name));
        } catch (IOException e) {
    
    
            e.printStackTrace();
            System.out.println("IO异常,downLoder出现问题");
        }
    }
}

导入jar包的方法:创建lib包,复制jar包到lib目录下,右键lib选择Add as library…

2.实现Runnable接口

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

//创建线程的方式2: 实现Runnable接口;实现run()方法;创建线程对象,调用start()方法启动线程
public class testThread03 implements Runnable{
    
    
    @Override
    public void run() {
    
    
        for(int i = 0;i <10; i ++){
    
    
            System.out.println("我是线程体" + i);
        }
    }

    public static void main(String[] args) {
    
    
        //创建Runnable接口的实现类对象
        testThread03 tt = new testThread03();
        //创建线程对象,通过线程对象来开启线程-----代理
//        Thread th = new Thread(tt);
//        th.start();
        new Thread(tt).start();

        for(int i = 0;i <50; i ++){
    
    
            System.out.println("我是主线程体" + i);
        }
    }
}

利用Runnable接口,下载图片:

import org.apache.commons.io.FileUtils;

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

//练习thread,实现多线程同步下载图片
public class testThread04 implements Runnable{
    
    
    private String url;
    private String name;

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

    @Override
    public void run() {
    
    
        webDownLoder02 wb = new webDownLoder02();
        wb.downLoder(url,name);
        System.out.println("上传图片" + name);
    }

    public static void main(String[] args) {
    
    
        testThread04 t = new testThread04("https://ss.html.cn/upload/article/000/000/016/603279dddcd25168.jpg-600","1.png");
        new Thread(t).start();

    }
}
//下载器
class webDownLoder02{
    
    
    //下载方法
    public void downLoder(String url,String name){
    
    

        try {
    
    
            FileUtils.copyURLToFile(new URL(url),new File(name));
        } catch (IOException e) {
    
    
            e.printStackTrace();
            System.out.println("IO异常,downLoder出现问题");
        }
    }
}

Thread和Runnable对比:

  • 继承Thread类:启动线程:子类对象.start();
    不建议使用,避免OOP编程单继承的局限性

  • 实现Runnbable接口:启动线程:传入目标对象.Thread对象.start()
    推荐使用Runnable,避免单进程局限性,方便同一个对象被多个线程使用。

模拟抢火车票

//问题:多个线程操作同一个资源,进程不安全,数据紊乱
public class testThread05 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-- + "票");
        }
    }
    public static void main(String[] args) {
    
    
        testThread05 t = new testThread05();
        new Thread(t,"凸凸").start();
        new Thread(t,"凹凹").start();
        new Thread(t,"黄牛").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("兔子")&& (i %10 == 0)){
    
    
                try {
    
    
                    Thread.sleep(5);
                } catch (InterruptedException e) {
    
    
                    e.printStackTrace();
                }
            }
            //判断比赛是否结束
            boolean flag = gameOver(i);
            if(flag == true){
    
    
                break;
            }
            System.out.println(Thread.currentThread().getName() + "跑了" + i + "步");
        }
    }

    //判断比赛是否结束
    private boolean gameOver(int step){
    
    
        if(winner != null){
    
    
           return true;
        }else if(step >= 100){
    
    
            winner = Thread.currentThread().getName();
            System.out.println("winner is" + winner);
            return true;
        }else {
    
    
            return false;
        }
    }

    public static void main(String[] args) {
    
    
        Race race = new Race();
        new Thread(race,"兔子").start();
        new Thread(race,"乌龟").start();
    }
}

3.callable接口(了解)

实现Callable接口,需要返回值类型
重写call方法,需要抛出方法
创建目标对象
创建执行服务:ExecutorService ser=Executors.newFixedThreadPool(1);
提交执行:Future result1=ser.submit(t1);
获取结果:boolean r1=result1.get();
关闭服务:ser.shutdownNow();

import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.concurrent.*;

public class testCallable implements Callable<Boolean> {
    
    

    private String url;
    private String name;

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

    @Override
    public Boolean call() {
    
    
        webDownLoder03 wb = new webDownLoder03();
        wb.downLoder(url,name);
        System.out.println("上传图片" + name);
        return true;
    }

    public static void main(String[] args) throws ExecutionException, InterruptedException {
    
    
        testCallable t1 = new testCallable("https://ss.html.cn/upload/article/000/000/016/603279dddcd25168.jpg-600","1.png");
        //创建执行服务
        ExecutorService ser= Executors.newFixedThreadPool(1);
        //提交执行
        Future<Boolean> r1 = ser.submit(t1);
        //获取结果
        boolean rs1 = r1.get();
        //关闭服务
        ser.shutdownNow();
    }
}
class webDownLoder03{
    
    
    //下载方法
    public void downLoder(String url,String name){
    
    

        try {
    
    
            FileUtils.copyURLToFile(new URL(url),new File(name));
        } catch (IOException e) {
    
    
            e.printStackTrace();
            System.out.println("IO异常,downLoder出现问题");
        }
    }
}

优点:
可以定义返回值

可以抛出异常

Guess you like

Origin blog.csdn.net/weixin_42226721/article/details/121508176