大家好,今天继续多线程!这期是和上一期连接起来的,大家可以连着看!
- 方法三:实现Callable接口(目前了解即可)
- 实现Callable接口,需要返回值类型。
- 重写call方法,需要抛出异常。
- 创建目标对象。
- 创建执行服务:ExecutorService service = Executors.newFixedThreadPool(1);
- 提交执行:Future result = service.submit(t1);
- 获取结果:boolean r1 = result.get();
- 关闭服务: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表达式(函数式编程)
- 避免匿名内部类太多
- 可以让你的代码看起很简洁
- 去掉没用的代码,只留下核心逻辑
- 函数式接口
- 只有一个抽象方法的接口,叫做函数式接口。
public interface Runnable {
public abstract void run();
}
- 我们可以通过Lamda表达式来创建该函数式接口的对象。
- 案例(通过各种内部类)
先写一个接口,再写一个实现该接口的类,然后调用他们
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();
}
- 接口对象 = 参数值【值,不加类型】->函数主体;
- 一个参数和多个函数代码行,就需要加括号和花括号;
四、线程状态
- 线程方法
- setPriority(int newPriority) 更改线程先级
- static void sleep(long millis) 在指定的毫秒数内让正在执行的线程休眠
- void join() 等待线程终止
- static void yield() 暂停当前执行的线程,并执行其他线程
- void interrupt() 中断线程,别用这个方式
- boolean isAlive() 测试线程是否处于活跃状态
- 停止线程
- 不推荐使用JDK提供的stop()、destory()方法。他们已经废弃
- 推荐让线程自己停下来。
- 建议使用一个标志位终止变量。
- 线程休眠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());
}
}
}
- 线程礼让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()+"线程已经结束");
}
}
- 线程强制执行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);
}
}
}
- 线程状态观测
新生 就绪 运行 阻塞/死亡
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);
}
}
}
- 线程优先级(控制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());
}
}
- 守护线程(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("拜拜了您嘞");
}
}