狂神说Java的多线程课程总结

一、这次课程敲的代码

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fCaXfNya-158692286
在这里插入图片描述

二、主要内容

  • 新建线程的三个方法。
	package com.newThread;
	
	import java.util.concurrent.Callable;
	import java.util.concurrent.ExecutionException;
	import java.util.concurrent.FutureTask;
	
	public class NewThread {
	    public static void main(String[] args) throws ExecutionException, InterruptedException {
	
	        new yang().start();
	
	        //new jie().run();
	        new Thread(new jie()).start();
	
	        // 通过实现Callable接口来创建线程的开启方法
	        FutureTask<Integer> futureTask = new FutureTask<Integer>(new wei());
	        new Thread(futureTask).start();
	        Integer integer = futureTask.get();
	        System.out.println(integer);
	    }
	}
	
	// 1.继承Thread类
	class yang extends Thread{
	    @Override
	    public void run() {
	        System.out.println("yang这个线程被创建了!!!");
	    }
	}
	
	// 2.实现runnable接口
	class jie implements Runnable{
	    @Override
	    public void run() {
	        System.out.println("jie这个线程被创建了!!!");
	    }
	}
	
	// 3.实现Callable接口
	class wei implements Callable<Integer>{
	
	    @Override
	    public Integer call() throws Exception {
	        System.out.println("wei这个线程被创建了!!!");
	        return 123;
	    }
	}
  • 线程插队

thread.join(); 在一个线程里面强行插入另外一个线程,直到插入的线程执行结束才回来执行原线程。

  • 线程停止

1.建议线程正常停止–>利用次数,不建议死循环
2.建议使用标志位–>设置一个标志位
3.不要使用stop或者destroy等过时或者jdk官网不建议使用的方法

    // 1.设置一个标识位
    private boolean flag = true;


    @Override
    public void run() {
        int i = 0 ;
        while (flag){
            System.out.println("线程运行了"+i++);
        }
    }

    // 2.设置一个公开的方法来停止线程,转换标志位
    public void stop(){
        this.flag = false;
    }
  • 线程礼让

Thread.yield(); 让当前线程让出时间片,让其他线程去执行,这个就好像比赛跑步,我让你10s,跑不跑得赢可是另外一回事。

	package com.yang;
	
	// 礼让线程,让出当前执行线程,但不阻塞,运行状态改成就绪状态
	// 礼让不一定成功,要看CPU的心情
	public class TestYield {
	    public static void main(String[] args) {
	        Myyield myyield = new Myyield();
	
	        new Thread(myyield,"a").start();
	    }
	}
	
	class Myyield implements Runnable{
	    @Override
	    public void run() {
	        System.out.println(Thread.currentThread().getName()+"线程开始");
	        Thread.yield();
	        System.out.println(Thread.currentThread().getName()+"线程结束");
	    }
	}
  • 线程状态
	public static enum Thread.State
	extends Enum<Thread.State>
	
	线程状态。
	一个线程可以有以下规定: 
		NEW
		线程尚未开始在这个国家。 
		RUNNABLE
		处于这种状态中的java虚拟机执行的线程。 
		BLOCKED
		线程阻塞等待监控锁在这个国家。 
		WAITING
		处于这种状态的线程被无限期地等待另一个线程来执行特定的动作。 
		TIMED_WAITING
		处于这种状态的线程正在等待另一个线程上执行一个动作指定的等待时间。 
		TERMINATED
		处于这种状态的线程退出。 
	一个线程可以在一个给定的时间点上只有一个状态。这些状态是不反映任何操作系统线程状态的虚拟机状态。

  • 线程优先级

static int ---------MAX_PRIORITY
线程可以拥有的最大优先级。

static int ---------MIN_PRIORITY
线程可以拥有的最小优先级。

static int -------- NORM_PRIORITY
被分配给线程的默认优先级。

void setPriority(int newPriority)
更改此线程的优先级。

int getPriority()
返回此线程的优先级。

  • 守护线程
   God god = new God();
   You you = new You();

   Thread thread = new Thread(god);
   thread.setDaemon(true); // 默认的是false,表示的是用户线程,正常的都是用户线程

   thread.start(); // 上帝守护线程启动

   new Thread(you).start();
  • 实现Callable接口来创建线程

使用callable好处
1.可以定义返回值
2.可以跑出异常

	package com.yang;
	
	import java.util.concurrent.*;
	
	/**
	 * 使用callable好处
	 * 1.可以定义返回值
	 * 2.可以跑出异常
	 */
	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() {
	        WebDownLoader webDownLoader = new WebDownLoader();
	        webDownLoader.downloader(url,name);
	        System.out.println("下载了文件名为:" + name);
	        return true;
	    }
	
	    public static void main(String[] args) throws ExecutionException, InterruptedException {
	        TestCallable t1 = new TestCallable("https://wx3.sinaimg.cn/mw690/91722dd1ly1gde42g94laj21ho1zkhdt.jpg","祖儿1.jpg");
	        TestCallable t2 = new TestCallable("https://wx2.sinaimg.cn/mw690/91722dd1ly1gde42j6jmpj21ho1zkhdt.jpg","祖儿2.jpg");
	        TestCallable t3 = new TestCallable("https://wx3.sinaimg.cn/mw690/91722dd1ly3gd444pbhpaj216o1kw4qp.jpg","祖儿3.jpg");
	
	        // 创建执行服务
	        ExecutorService ser = Executors.newFixedThreadPool(3);
	
	        // 提交执行
	        Future<Boolean> r1 = ser.submit(t1);
	        Future<Boolean> r2 = ser.submit(t2);
	        Future<Boolean> r3 = ser.submit(t3);
	
	        // 获取结果
	        Boolean rs1 = r1.get();
	        Boolean rs2 = r2.get();
	        Boolean rs3 = r3.get();
	
	        // 关闭服务
	        ser.shutdown();
	    }
	}

  • lambda表达式
	// 演变:从外部实现类-》静态内部类-》局部内部类-》匿名内部类—》lambda表达式
	
	// lambda表达式只能有一行的情况下才能简化成一行,如果有多行,需要代码块
	// 前提是接口为函数式接口,也就是只有一个方法,就先线程里的只有一个run方法
	// 多个参数也可以去掉参数类型,要去掉的话需要全部都去掉,必须街上括号
	package Lambda;
	
	public class LambdaExpression {
	
	    public static void main(String[] args) {
	        
	//        Ilove love = new Ilove() {
	//            @Override
	//            public void love() {
	//                System.out.println("i dont love you");
	//            }
	//        };
	        
	//        Ilove love = ()->{
	//            System.out.println("i dont love you");
	//        };
	
	        Ilove love = () -> System.out.println("i dont love you");
	        love.love();
	    }
	}
	
	interface Ilove{
	    void love();
	}

三、比较重要的部分

  • synchronized

线程不安全引发的思考,如何保证程序符合正常逻辑,这里使用同步方法、同步代码块

	// 线程不安全
	public class UnSafeBuyTicket {
	    public static void main(String[] args) {
	        BuyTicket buyTicket = new BuyTicket();
	        new Thread(buyTicket,"苦逼的我").start();
	        new Thread(buyTicket,"黄牛").start();
	        new Thread(buyTicket,"牛逼的你们").start();
	    }
	}
	
	class BuyTicket implements Runnable{
	
	    private  int ticket = 10;
	    boolean flag = true;  // 外部停止方式
	
	    @Override
	    public void run() {
	        while (flag){
	            try {
	                buy();
	            } catch (InterruptedException e) {
	                e.printStackTrace();
	            }
	        }
	    }
	
	    // synchronized 同步方法,锁的是this
	    private synchronized void buy() throws InterruptedException {
	        if (ticket<=0){
	            flag = false;
	            return;
	        }
	        Thread.sleep(1000);
	        System.out.println(Thread.currentThread().getName()+"->"+ticket--);
	
	    }
	}

并发编程JUC

	import java.util.ArrayList;
	import java.util.List;
	import java.util.concurrent.CopyOnWriteArrayList;
	
	// 测试juc安全类型的集合
	public class TestJUC {
	    public static void main(String[] args) throws InterruptedException {
	//        CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<String>();
	        List<String> list = new ArrayList<String>();
	        for (int i = 0; i < 10000; i++) {
	            new Thread(()-> list.add(Thread.currentThread().getName())).start();
	        }
	//        Thread.sleep(1000);
	        System.out.println(list.size());
	    }
	}
  • Lock
package lock;

import java.util.concurrent.locks.ReentrantLock;

// jdk5产生
public class TestLock {
    public static void main(String[] args) {
        TestLock2 lock2 = new TestLock2();

        new Thread(lock2,"1").start();
        new Thread(lock2,"2").start();
        new Thread(lock2,"3").start();
    }
}

class TestLock2 implements Runnable{

    int ticketNum = 10;

    // 定义lock锁
    private final ReentrantLock lock = new ReentrantLock();


    @Override
    public void run() {
        while(true){
            try {
                lock.lock();
                if (ticketNum>0){
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(ticketNum--);
                }else {
                    break;
                }
            }finally {
                // 手动加锁 解锁
                lock.unlock();
            }
      }
    }
}

在这里插入图片描述
在这里插入图片描述

  • 代理

不过这个我不知道和线程有什么关系…
两个对象实现同一个接口然后将一个对象传给另外一个通过构造函数。这样就实现代理。分工合作

	package proxy;
	
	/**
	 * 静态代理模式总结:
	 * 真实对象和代理对象都要实现同一个接口
	 * 代理对象要代理真实角色
	 *
	 * 好处:
	 *      代理对象可以做很多真实对象做不了的事情
	 *      真实对象专注做自己的事情
	 */
	public class staticProxy {
	    public static void main(String[] args) {
	        You you = new You();
	        new Thread( ()-> System.out.println("I love you!")).start();
	
	        WeddingCompany weddingCompany = new WeddingCompany(you);
	        weddingCompany.HappyMarry();
	    }
	}
	
	interface Marry{
	
	    void HappyMarry();
	}
	
	// 真实角色,你去结婚
	class You implements Marry{
	
	    @Override
	    public void HappyMarry() {
	        System.out.println("I am getting married!");
	    }
	}
	
	// 代理角色,帮助你结婚
	class WeddingCompany implements Marry{
	
	    private Marry target;
	    public WeddingCompany(Marry target){
	        this.target = target;
	    }
	
	    @Override
	    public void HappyMarry() {
	        before();
	        this.target.HappyMarry();  // 真实对象去结婚
	        after();
	    }
	
	    private void after() {
	        System.out.println("结婚之后,嘻嘻");
	    }
	
	    private void before() {
	        System.out.println("结婚之前,哈哈");
	    }
	}
  • 线程池 前文实现Callable接口有涉及

前文实现Callable接口有涉及返回值,这里这案例没有返回值。执行方法不同execute、submit

	package com.yang;
	
	import java.util.concurrent.ExecutorService;
	import java.util.concurrent.Executors;
	
	public class TestPool {
	    public static void main(String[] args) {
	        // 1.创建服务,创建线程池
	        ExecutorService service = Executors.newFixedThreadPool(10);
	
	        // 执行
	        service.execute(new MyThread());
	        service.execute(new MyThread());
	        service.execute(new MyThread());
	        service.execute(new MyThread());
	
	        // 2.关闭连接
	        service.shutdown();
	    }
	}
	
	class MyThread implements Runnable{
	    @Override
	    public void run() {
	        System.out.println(Thread.currentThread().getName());
	    }
	}

四、记得回来看,虽然代码似乎有点多,但是并不复杂,重在理解

  • 6
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值