Day05 学习java 2020-10-2

学习java Day05

多线程

多线程的3种方式

  • 继承自Thread类
public class RunTest extends Thread{
	public void run(){
		for(int i=0;i<20;i++){
			System.out.println("RunTest"+i);
		}
	}
	public static void main(String[] args){
		RunTest runtest = new RunTest();
		runtest.start();  // 调用start() 才是开启多线程,调用run()只会普通调用方法
		System.out.println("Main");
	}
}
//结果
Main
RunTest0
RunTest1
RunTest2
  • 实现Runnable接口**(因为java是单继承推荐使用接口实现)**
public class RunTest implements Runnable{
	public void run(){
		for(int i=0;i<20;i++){
		System.out.println("RunTest"+i);
		}
	}
	public static void main(String[] args){
		RunTest runtest = new RunTest();
		new Thread(runtest ).start(); // 需要通过创建Thread对象,传入重写Runnable接口的对象开启线程
		System.out.println("Main");
	}
}
  • 实现Callable接口 (重写的是call方法,有返回值,能处理异常)
public class RunTest implements Callable<String>{
    public String call() throws Exception {
        for(int i=0;i<20;i++){
            System.out.println("RunTest"+i);
        }
        return "结束了";
    }
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        ExecutorService ser = Executors.newFixedThreadPool(3);
        RunTest runTest = new RunTest();
        Future<String> s= ser.submit(runTest);
        //接收返回值会进行堵塞,
        //String str = s.get();
        //System.out.println(str);
        System.out.println("main");
        ser.shutdown();
    }
}

线程的常用方法

  1. 获取当前线程的名称:
    Thread.currentThread().getName()
  2. 让线程阻塞(休眠),不释放锁
    Thread.sleep(long mills) // 休眠时间,毫秒值
  3. 礼让线程 :线程礼让不一定成功(看CPU的调度)
    Thread.yield()
  4. 让当前线程停止执行(线程对象的方法)
    thread.join(); //直到thread线程执行结束,当前线程再执行
    thread.join(long mills); // 等待mills毫秒的时间再执行
  5. 得到线程状态(线程对象的方法)
    Thread.State state = thread.getState()
  6. 设置线程优先级 (优先级从1到10 越高越有可能先执行,默认优先级都为5)(线程对象的方法)
    thread.setPriority();
  7. 设置为守护线程(jvm虚拟机不必等待守护进程执行完毕)(线程对象的方法)
    thread.setDaemon(true) // 设为true,默认为false

多线程的并发问题

  • 多个线程对同一个资源进行操作,会出现并发问题
public class BuyTicket implements Runnable{
	private int ticket = 10;  // 假定总共有10张票
	public void run(){
		while(ticket>0){
            try {
            // 增加睡眠时间,提高时间发生可能性
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
			System.out.println(Thread.currentThread().getName() + "买了第" + ticket + "张票");
			ticket--;
		}
	}
	public static void main(String[] args){
		BuyTicket buy= new BuyTicket ();  //定义一个买票窗口
		new Thread(buy,"小A").start();   // 定义3个买票人员
		new Thread(buy,"小B").start(); 
		new Thread(buy,"小C").start(); 
	}
}
//结果(每次的结果可能不同) 总之结果和我们预期的不一样,出现了票数一样,0票和负票 
小A买了第10张票
小B买了第10张票
小C买了第10张票
小A买了第7张票
小B买了第6张票
小C买了第5张票
小A买了第4张票
小B买了第3张票
小C买了第2张票
小A买了第1张票
小B买了第0张票
小C买了第-1张票

处理并发问题的3种方式

每个对象都是一把锁

  1. 设为同步方法 : 将方法用 synchronized 修饰
public class BuyTicket implements Runnable{
    private int ticket = 1000;  // 假定总共有10张票
    public void run(){
        System.out.println(Thread.currentThread().getName());
        while(ticket>0){
            buy();
        }
    }
    private synchronized void buy() {
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + "买了第" + ticket-- + "张票");
    }
    public static void main(String[] args){
        BuyTicket buy= new BuyTicket ();  //定义一个买票窗口
        new Thread(buy,"小A").start();
        new Thread(buy,"小B").start();
        new Thread(buy,"小C").start();
        System.out.println("startALl==================");
    }
}
  1. 设定同步代码块: 锁一部分 synchronized(obj){…} 锁对象最好是选择操作的同一个资源对象
private Integer ticket = 10;  // 假定总共有10张票
    private final Object o;   // 锁对象
    public BuyTicket2(Object obj){
        this.o=obj;
    }
    public void run(){
        System.out.println(Thread.currentThread().getName());
        while(true){
            synchronized (o){
                if(ticket>0){
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + "买了第" + ticket-- + "张票");
                }else{
                    break;
                }
            }
        }
    }
  1. 使用Lock对相同资源处理的部分进行锁住
private int ticket = 10;  // 假定总共有10张票
    // 定义同步锁
    private final ReentrantLock lock = new ReentrantLock();
    public void run(){
        System.out.println(Thread.currentThread().getName());
        while(true){
            lock.lock();
            try{
                if(ticket>0){
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + "买了第" + ticket-- + "张票");
                }else{
                    break;
                }
            }finally {
                lock.unlock();
            }
        }
    }

线程间通信

  • wait() 会释放锁,进入等待池
  • notify() 唤醒等待池中该对象锁的一个线程(由cpu决定)
  • notifyAll() 唤醒等待池中该对象锁的所有线程,多个线程会去抢夺锁

Lambda表达式

  • 只有当接口是函数式接口可以使用(一个接口中只定义了一个抽象方法)
  • lambda 其实就是对匿名内部类的简化
public class LambdaTest {
    public static void main(String[] args) {
    // 匿名内部类实现
        lambda ld = new lambda() {
            @Override
            public void show() {
                System.out.println("实现方法。");
            }
        };
        ld.show();
  // lambda表达式实现  (这是没有参数的,又只有一行输出语句,最简形式)
        ld = ()-> System.out.println("lambda 实现。");
        ld.show();
    }
}
interface lambda{
    void show();
}

普通的多参数带返回值的lambda简化

public class LambdaTest {
    public static void main(String[] args) {
        lambda ld = new lambda() {
            @Override
            public String show(int a,int b) {
                System.out.println("实现方法。" +a);
                System.out.println("实现方法。" +b);
                return "匿名内部类";
            }
        };
        System.out.println(ld.show(13,14));
        ld = (a ,b)-> {
            System.out.println("lambda 实现。" + a);
            System.out.println("lambda 实现。" + b);
            return "Lambda表达式";
        };
        System.out.println(ld.show(13,14));
    }
}
interface lambda{
    String show(int a,int b);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值