多线程(续)

大家好,今天继续多线程!这期是和上一期连接起来的,大家可以连着看!

  • 方法三:实现Callable接口(目前了解即可)
  1. 实现Callable接口,需要返回值类型。
  2. 重写call方法,需要抛出异常。
  3. 创建目标对象。
  4. 创建执行服务:ExecutorService service = Executors.newFixedThreadPool(1);
  5. 提交执行:Future result = service.submit(t1);
  6. 获取结果:boolean r1 = result.get();
  7. 关闭服务:service.shutdownNow();
public class CallableProject implements Callable<Boolean> {
	private String urlString;
	private String nameString;
	public CallableProject(String urlString, String nameString) {
		super();
		this.urlString = urlString;
		this.nameString = nameString;
	}
	@Override
	public Boolean call() throws Exception {
		PictureLoader1 pictureLoader = new PictureLoader1();
		pictureLoader.load(urlString, nameString);
		System.out.println("已下载图片到文件:"+nameString);
		return true;
	}
	public static void main(String[] args) throws InterruptedException, ExecutionException {
		CallableProject picturesLoad1 = new CallableProject("https://img-blog.csdn.net/20180531234717825?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM3NjM4MDYx/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70", "p1.jpg");
		CallableProject picturesLoad2 = new CallableProject("https://img-blog.csdn.net/20180531234216145?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM3NjM4MDYx/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70", "p2.jpg");
		CallableProject picturesLoad3 = new CallableProject("https://img-blog.csdn.net/20180531234329372?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM3NjM4MDYx/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70", "p3.jpg");
		CallableProject picturesLoad4 = new CallableProject("https://img-blog.csdn.net/20180531234601650?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM3NjM4MDYx/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70", "p4.jpg");
		ExecutorService service = Executors.newFixedThreadPool(4);
		Future<Boolean> result1 = service.submit(picturesLoad1);
		Future<Boolean> result2 = service.submit(picturesLoad2);
		Future<Boolean> result3 = service.submit(picturesLoad3);
		Future<Boolean> result4 = service.submit(picturesLoad4);
		boolean r1 = result1.get();
		boolean r2 = result2.get();
		boolean r3 = result3.get();
		boolean r4 = result4.get();
		service.shutdownNow();
	}
}
//下载器
class PictureLoader1 {
	//下载方法
	public void load(String purl, String fname) {
		try {
			FileUtils.copyURLToFile(new URL(purl), new File(fname));
		} catch (Exception e) {
			e.printStackTrace();
			System.out.println("图片下载异常");
		}
	}
}
三、静态代理模式
  • 你:真实角色
  • 婚庆公司:代理你,帮你处理结婚的事
  • 都实现结婚借口即可
  • 好处:代理对象可以做真实对象做不了的事情;真实对象只需要做好自己的事情就好。
public class Marry {
	public static void main(String[] args) {
		new weddingCompany(new newPerson()).marry();
	}
}
interface marry {
	void marry();
}
class newPerson implements marry {
	public void marry() {
		System.out.println("我要结婚了!!!");
	}
}
class weddingCompany implements marry {
	private newPerson person;
	public weddingCompany(newPerson nPerson) {
		this.person = nPerson;
	}
	public void marry() {
		befor();
		person.marry();
		after();
	}
	void befor() {
		System.out.println("结婚之前要布置现场");
	}
	void after() {
		System.out.println("结婚之后要收尾款");
	}
}
三、Lamda表达式(函数式编程)
  • 避免匿名内部类太多
  • 可以让你的代码看起很简洁
  • 去掉没用的代码,只留下核心逻辑
  1. 函数式接口
    • 只有一个抽象方法的接口,叫做函数式接口。
public interface Runnable {
	public abstract void run();
}
  • 我们可以通过Lamda表达式来创建该函数式接口的对象。
  1. 案例(通过各种内部类)
先写一个接口,再写一个实现该接口的类,然后调用他们
public class LamdaExpression {
	public static void main(String[] args) {
		imLam im = new imLamd();
		im.speak();
	}
}
interface imLam {
	void speak();
}
class imLamd implements imLam {
	@Override
	public void speak() {
		System.out.println("我不想说话");
	}
}
觉得很麻烦,就改装成为静态内部类,写在类里面的静态类
public class LamdaExpression {
	public static void main(String[] args) {
		imLam im = new imLamd();
		im.speak();
	}
	static class imLamd implements imLam {
		@Override
		public void speak() {
			System.out.println("我不想说话");
		}
	}
}
interface imLam {
	void speak();
}
还是觉得很麻烦,就改成了局部内部类,写在方法里的类
public class LamdaExpression {
	public static void main(String[] args) {
		class imLamd implements imLam {
			@Override
			public void speak() {
				System.out.println("我不想说话");
			}
		}
		imLam im = new imLamd();
		im.speak();
	}
}
interface imLam {
	void speak();
}
依然觉得很麻烦,再次改成匿名内部类,{},没有类名,必须借助接口或者父类
public class LamdaExpression {
	public static void main(String[] args) {
		imLam i = new imLam() {
			@Override
			public void speak() {
				System.out.println("我不想说话");
			}
		};
		i.speak();
	}
}
interface imLam {
	void speak();
}
还是觉得很麻烦,于是,就演变成为了使用Lamda表达式来表示
public class LamdaExpression {
	public static void main(String[] args) {
		imLam i = ()->{
			System.out.println("我不想说话");
		};
		i.speak();
	}
}
interface imLam {
	void speak();
}
  • 接口对象 = 参数值【值,不加类型】->函数主体;
  • 一个参数和多个函数代码行,就需要加括号和花括号;
四、线程状态

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

  1. 线程方法
  • setPriority(int newPriority) 更改线程先级
  • static void sleep(long millis) 在指定的毫秒数内让正在执行的线程休眠
  • void join() 等待线程终止
  • static void yield() 暂停当前执行的线程,并执行其他线程
  • void interrupt() 中断线程,别用这个方式
  • boolean isAlive() 测试线程是否处于活跃状态
  1. 停止线程
  • 不推荐使用JDK提供的stop()、destory()方法。他们已经废弃
  • 推荐让线程自己停下来。
  • 建议使用一个标志位终止变量。
    在这里插入图片描述
  1. 线程休眠sleep
  • sleep指定当前线程堵塞的毫秒数
  • sleep存在异常InterruptedException
  • sleep时间达到后线程进入就绪状态
  • sleep可以模拟网络延迟,倒计时
  • 每个对象都有一个锁,sleep不会释放锁
倒计时每秒
public class daoTime {
	public static void main(String[] args) {
		run();
	}
	public static void tenTime() {
		int num=10;
		while(true) {
			new Thread().sleep(1000);
			System.out.println(num--);
			if(num<=0) {
				break;
			}
		
		}
	
	}
}
按秒输出时间
public class TimeProject {
	public static void main(String[] args) {
		Date s = new Date(System.currentTimeMillis());
		while(true) {
			Thread.sleep(1000);
			System.out.println(new SimpleDateFormate("HH:mm:ss").format(s);
			s = new Date(System.currentTimeMillis());
		}
	}
}
  1. 线程礼让yield
  • 礼让线程,让当前正在执行的线程暂停,但不堵塞
  • 将线程从运行状态转为就绪状态
  • *让CPU重新调度,礼让不一定成功,看CPU心情!!
public class TestYield {
	public static void main(String[] args) {
		myYield m = new myYield();
		new Thread(m,"a").start();
		new Thread(m,"b").start();
	}
}
class myYield {
	@Override
	public void run() {
		System.out.println(Thread.currentThread() + "线程开始执行");
		Thread.yield();
		System.out.println(Thread.currentThread() + "线程结束");
	}
}
public class MyYieldTest extends Thread {
	public static void main(String[] args) {
		MyYieldTest myYieldTest = new MyYieldTest();
		new Thread(myYieldTest,"a").start();
		new Thread(myYieldTest,"b").start();
	}
	@Override
	public void run() {
		System.out.println(Thread.currentThread().getName()+"线程开始执行");
		Thread.yield();
		System.out.println(Thread.currentThread().getName()+"线程已经结束");
	}
}
  1. 线程强制执行join(join合并线程,待此线程执行完成后,再执行其他线程,其他线程堵塞!)
public class TestJoin implements Runnable {
	@Override
	public void run() {
		for(int i=0; i<1000; i++) {
			System.out.println("vip来了" + i);
		}
	}
	public static void main(String[] args) throws InterruptedException {
		Thread thread = new Thread(new TestJoin());
		thread.start();
		for(int j=0; j<100; j++) {
			if(j==30) {
				thread.join();
			}
			System.out.println("main方法"+j);
		}
	}
}
  1. 线程状态观测
    新生 就绪 运行 阻塞/死亡
public class ThState {
	public static void main(String[] args) throws InterruptedException {
		Thread thread = new Thread(()->{
			for(int i=0; i<5; i++) {
				try {
					Thread.sleep(19);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
			System.out.println("^^^^^^^^");
		});
		//观察状态
		Thread.State state = thread.getState();
		System.out.println(state);
		//观察启动后
		thread.start();
		state = thread.getState();
		System.out.println(state);//Run
		//只要线程不终止,就一直输出状态
		while(state != thread.getState().TERMINATED) {
			Thread.sleep(100);
			state = thread.getState();//更新线程状态
			System.out.println(state);
		}
	}
}
  1. 线程优先级(控制CPU)
    getPriority()
    setPriority(int xxx)
    优先级默认是5,最高是10
    优先级高可能先跑,但不是一定的,这都是看CPU的心情
public class ThPropertiesTest implements Runnable {
	public static void main(String[] args) {
		System.out.println(Thread.currentThread().getName()+"-->"+Thread.currentThread().getPriority());
		ThPropertiesTest t = new ThPropertiesTest();
		Thread t1 = new Thread(t);
		Thread t2 = new Thread(t);
		Thread t3 = new Thread(t);
		Thread t4 = new Thread(t);
		t1.start();
		t2.setPriority(4);
		t2.start();
		t3.setPriority(8);
		t3.start();
		t4.setPriority(2);
		t4.start();
	}
	@Override
	public void run() {
		System.out.println(Thread.currentThread().getName()+"-->"+Thread.currentThread().getPriority());
	}
}
  1. 守护线程(daemon)
  • 用户线程和守护线程
  • 虚拟机必须保护用户线程执行完毕main
  • 虚拟机不用等待守护线程执行完毕gc
  • 如:后台记录操作日志、监控内存、垃圾回收…
  • deamon=false。示为用户线程;true为守护线程;一般都为用户线程。
上帝守护着你
public class TsetDeamon {
	public static void main(String[] args) {
		god g = new god();
		You y = new You();
		Thread thread = new Thread(g);
		thread.setDaemon(true);
		thread.start();
		new Thread(y).start();
	}
}
//上帝
class god implements Runnable {
	@Override
	public void run() {
		while(true) {
			System.out.println("上帝会永远守护着你");
		}
	}
}
//你
class You implements Runnable {
	@Override
	public void run() {
		for(int year=0; year<50; year++) {
			System.out.println("我今年" + year + "岁");
		}
		System.out.println("拜拜了您嘞");
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值