多线程

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

实现多线程代码(继承thread类)

package demo1;

//创建线程方式一:继承Thread类,重写run()方法,调用start开启线程
//总结:注意,线程开启不一定立即执行,由CPU调度执行
public class testThread1 extends Thread{

	@Override
	public void run() {
		for(int i=0;i<200;i++)
		{
			System.out.println("我在看代码"+i);
		}
	}
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		//main 线程,主线程
		//创建一个线程对象
		testThread1 testThread1 = new testThread1();
		
		//调用start()方法开启线程
		testThread1.start();
		for(int i=0;i<1000;i++)
		{
			System.out.println("我在学习"+i);
		}
		
	}

}

多线程网图下载代码

package com.xwc.demo01;

import org.apache.commons.io.FileUtils;

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

/**
 * @author weichi.xwc
 * @create 2020-11-16 9:29 上午
 */
public class TestThread extends Thread {
    String url;
    String name;

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

    @Override
    public void run() {
        WebDownloader webDownloader = new WebDownloader();
        try {
            webDownloader.downLoader(url,name);
            System.out.println("下载了"+name);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    public static void main(String[] args) {
        TestThread t1 = new TestThread("https://img2020.cnblogs.com/blog/381412/202011/381412-20201115224545609-1066153938.png","1.png");
        TestThread t2 = new TestThread("https://img2020.cnblogs.com/blog/381412/202011/381412-20201115224413067-1198543412.png","2.png");
        TestThread t3 = new TestThread("https://img2020.cnblogs.com/blog/381412/202011/381412-20201115224626988-1300472311.png","3.png");
        t1.start();
        t2.start();
        t3.start();
    }
}
//下载器
class WebDownloader{
    public void downLoader(String url,String name) throws IOException {
        FileUtils.copyURLToFile(new URL(url),new File(name));
    }
}

实现多线程代码(重写runnable接口)

public class TestThread implements Runnable{

    @Override
    public void run() {
        for(int i=0;i<200;i++)
        {
            System.out.println("我在看代码"+i);
        }
    }
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        //main 线程,主线程
        //创建一个线程对象
        TestThread testThread = new TestThread();
        Thread thread = new Thread(testThread);
        thread.start();
        for(int i=0;i<1000;i++)
        {
            System.out.println("我在学习"+i);
        }

    }

多线程并发抢票代码实现

package com.xwc.demo01;
//发现问题:多个线程操作同一个资源情况下,线程不安全,数据紊乱
public class TestThread implements Runnable{
    private int ticketNums = 10;
    @Override
    public void run() {
        while (ticketNums>0){
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+"拿到了第"+ticketNums+"张票");
            ticketNums--;
        }
    }
    public static void main(String[] args) {

        TestThread testThread = new TestThread();
        new Thread(testThread,"小明").start();
        new Thread(testThread,"小红").start();
        new Thread(testThread,"小徐").start();
    }

}

龟兔赛跑代码实现

public class Race implements Runnable{
    private static String winner;
    @Override
    public void run() {
        for (int i = 0; i <= 100; i++) {
            boolean flag = gameOver(i);
            if(Thread.currentThread().getName().equals("兔子") && i%50==0){
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            if(flag){
                break;
            }
            System.out.println(Thread.currentThread().getName()+"跑了"+i+"步");
        }
    }
    public Boolean gameOver(int steps){
        if(winner!=null){
            return true;
        }else if(steps>=100){
                winner = Thread.currentThread().getName();
                System.out.println("The winner is"+winner);
                return true;
            }
            return false;

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

实现Callable接口

步骤:

  1. 实现Callable接口,需要返回值类型
  2. 重写call方法,需要抛出异常
  3. 创建目标对象
  4. 创建执行服务:ExecutorService=Executor.newFixedThreadPool(1);
  5. 提交执行:Futureresult1=ser.submit(t1);
  6. 获取结果:boolean r1=result.get()
  7. 关闭服务:ser.shutdownNow();

静态代理

  • 真实对象和代理对象都要实现同一个接口
  • 代理对象要代理真实角色

好处:

代理对象可以做很多真实对象做不了的事情

真实对象专注做自己的事情

Lambda表达式

好处:

  • 避免匿名内部类定义过多
  • 其实质属于函数式编程的概念
  • 可以让代码看起来很简洁
  • 去掉了一堆没有意义的代码,只留下核心的逻辑

Functional Interface(函数式接口)
定义:
任何接口,如果只包含唯一一个抽象方法,那么它就是一个函数式接口。
对于函数式接口,可以通过lambda表达式来创建该接口的对象。

public class TestLambda1 {
    //2.静态内部类
    static class Love implements ILove {
​
        public void ILove(int a) {
            System.out.println("i like lambda" + a);
        }
    }
    public static void main(String[] args) {
      Love love=new Love();
      love.ILove(1);
      Love love1=new Love();
      love1.ILove(2);
        class Love implements ILove {
        //3.局部内部类
            public void ILove(int a) {
                System.out.println("i like lambda" + a);
            }
        }
        Love love2 = new Love();
        love2.ILove(3);
        //4.匿名内部类
        ILove iLove=new ILove() {
            @Override
            public void ILove(int a) {
                System.out.println("i like lambda" + a);
            }
        };
      iLove.ILove(4);
      //5.lambda表达式
        ILove iLove1=(int a)->{
            System.out.println("i like lambda" + a);
        };
        iLove1.ILove(5);
    }
}
//定义一个接口,只有一个方法,函数式接口
interface ILove{
    void ILove(int a);
}
    //1.普通实现
class Love implements ILove {
        @Override
    public void ILove(int a) {
        System.out.println("i like lambda" + a);
    }
}
public class TestLambda2 {
    public static void main(String[] args) {
        YouLove youLove=(a,b)->{
            System.out.println("一句话你说:"+a+b);
        };
        youLove.youLove(10,20);
    }
}
​
interface YouLove{
    void youLove(int a,int b);
}

总结:

  1. lambda表达式只能有一行代码的情况下才能简化为一行,如果有多行,那么就用代码块包裹
  2. 前提是接口为函数式接口
  3. 多个参数也可以去掉参数类型,要去掉就都去掉,必须加上括号。

线程停止实现代码

public class TestStop implements Runnable {
    private boolean flag=true;
    @Override
    public void run() {
        int i=0;
        while (flag){
            System.out.println("run.....Thread"+(i++));
        }
    }
    public void stop(){
        this.flag=false;
    }
​
    public static void main(String[] args) {
        TestStop testStop = new TestStop();
        new Thread(testStop).start();
        for (int i = 0; i <1000 ; i++) {
            System.out.println("main"+i);
            if (i==900){
                testStop.stop();
                System.out.println("线程停止了!");
            }
        }
    }
}

线程休眠(sleep)

  • sleep(时间)指定当前线程阻塞的毫秒数;
  • sleep存在异常InterruptedException
  • sleep时间到达后线程进入就绪状态
  • sleep可以模拟网络延时,倒计时等。
  • 每一个对象都有一个锁,sleep不会释放锁
public class TestSleep1 {
    public static void main(String[] args) {
    tenDown();
    //打印当前系统时间
        Date startTime=new Date(System.currentTimeMillis());//获取当前系统时间
        while (true){
            try {
                Thread.sleep(1000);
                System.out.println(new SimpleDateFormat("HH:mm:ss").format(startTime));
                startTime=new Date(System.currentTimeMillis());//更新时间
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    //模拟倒计时
    public static void tenDown(){
        int num=10;
        while (true){
            try {
                Thread.sleep(1000);
                if (num<=0){
                    break;
                }else{
                    System.out.println("倒计时!!!"+num--+"秒");
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

线程礼让

  • 礼让线程,让当前正在执行的线程暂停,但不阻塞
  • 将线程从运行状态转为就绪状态
  • 让cpu重新调度,礼让不一定成功!看CPU心情。
public class TestYield implements Runnable {
    public static void main(String[] args) {
        TestYield yield=new TestYield();
        new Thread(yield,"a").start();
        new Thread(yield,"b").start();
    }
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+"线程开始执行");
        Thread.yield();//礼让
        System.out.println(Thread.currentThread().getName()+"线程停止执行");
    }
}

线程强制执行(join)

join合并线程,待此线程执行完成后,再执行其他线程,其他线程阻塞
可以想象成插队

public class TestJoin implements Runnable {
    @Override
    public void run() {
        for (int i = 0; i <100 ; i++) {
            System.out.println("VIP线程来插队了!!!"+i);
        }
    }


        public static void main(String[] args) throws InterruptedException {
           Thread thread= new Thread(new TestJoin());

            for (int i = 0; i <400 ; i++) {
                System.out.println("主线程在排队!!!"+i);
                if (i==100){
                    thread.start();
                    thread.join();

            }
        }
    }
}```

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值