多线程
线程就是独立的执行路径
一个进程可以有多个线程
但是这些线程其实都是模拟出来的 真正的多线程是指cpu有多个
即使是在有一个cpu的情况下,在同一时间点 cpu只能执行一个代码,但因为cpu执行效率高 时间短,所以我们就会chans同时执行的错觉
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8wRoupOF-1586602729023)(C:\Users\you\AppData\Roaming\Typora\typora-user-images\image-20200411163136351.png)]
2.线程的创建方式
继承Thread类(重点)
1.继承Thread类 然后重写run方法
2.创建一个thread的对象 调用start方法开启多线程
public class TestThread extends Thread {
@Override
public void run() {
//run方法线程体
for (int i = 0; i <100 ; i++) {
System.out.println("run"+i);
}
}
public static void main(String[] args) {
//创建线程对象 调用start方法 开启线程
TestThread testThread = new TestThread();
testThread.start();
//main线程,主线程
for (int i = 0; i <10000 ; i++) {
System.out.println("main"+i);
}
}
}
程序运行结果可以看出 显示运行了main方法
但在main方法运行的中间也开了run方法的执行,两个线程实际上是同时在运行
运行的先后顺序是cpu调度的
小实例
//练习Thread,实现多线程同步下载图片
public class TestThread2 extends Thread{
private String url;//网络图片地址
private String name;//保存的文件名
public TestThread2(String url, String name) {
this.url = url;
this.name = name;
}
@Override
public void run() {
WebDonload webDonload = new WebDonload();
webDonload.download(url,name);
System.out.println("下载的文件名为"+name);
}
public static void main(String[] args) {
TestThread2 testThread1 = new TestThread2("http://img3.imgtn.bdimg.com/it/u=2534506313,1688529724&fm=26&gp=0.jpg","1");
TestThread2 testThread2 = new TestThread2("http://img4.imgtn.bdimg.com/it/u=1280325423,1024589167&fm=26&gp=0.jpg","2");
TestThread2 testThread3 = new TestThread2("http://t7.baidu.com/it/u=888206991,1760071208&fm=191&app=48&size=h300&n=0&g=4n&f=JPEG?sec=1853310920&t=cc5d57a46142087a2aa2124099bc6eec","3");
testThread1.start();
testThread2.start();
testThread3.start();
}
}
//类加载器 程序运行时加载 下载器
class WebDonload{
public void download(String url,String name){//获取网络图片的方法
try {
FileUtils.copyURLToFile(new URL(url),new File(name));
} catch (IOException e) {
e.printStackTrace();
System.out.println("io异常");
}
}
}
从结果发现并不是按照1,2,3的顺序进行下载的
实现Runnable接口(重点)
1.创建一个类去实现Runnable接口
2.重写run方法
3.创建一这个类的一个对象
4.用代理模式将这个对象传入Thread中然后.start
public class TestThread3 implements Runnable{
public void run() {
for (int i = 0; i <300 ; i++) {
System.out.println("这里是run"+i);
}
}
public static void main(String[] args) {
//创建runnable的对象
TestThread3 testThread3 = new TestThread3();
//创建一个thread对象
new Thread(testThread3).start();
for (int i = 0; i <2000 ; i++) {
System.out.println("这里是main方法"+i);
}
}
}
推荐使用这一种方法
避免单继承的局限性,灵活方便,方便一个对象被多个线程启用
例子二 龟兔赛跑
//多线程模拟龟兔赛跑
public class Race implements Runnable {
private static int race;
private static String winner;
public void run() {
//模拟龟兔的赛跑步数
for (int i = 0; i <=100 ; i++) {
if (Thread.currentThread().getName().equals("龟") && i%10==0){
try {
Thread.sleep(15);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//判断比赛是否结束
boolean flag=winner(i);
if (flag){
break;
}
System.out.println(Thread.currentThread().getName()+"跑了"+i+"步");
}
}
//判断谁先到达了100
public boolean winner(int step){
if (winner!=null) {
return true;
}
else if (step==100){
winner = Thread.currentThread().getName();
System.out.println("the winner is"+winner);
return true;
}
return false;
}
public static void main(String[] args) {
Race race = new Race();
new Thread(race,"兔").start();
new Thread(race,"龟").start();
}
}
实现Callable接口(了解)
静态代理
1.两个类都实现了同一个接口
2.其中的一个类能调用的方法更多
3.调用这个类去实现这个另一个类实现不了的方法
叫做代理
真实例子:结婚
你们要结婚
婚庆公司要帮你结婚
你们两个人办不下来结婚这个方法(布置,流程)
找到婚庆公司帮你们结婚
这就是代理了
多线程中的静态代理
public static void main(String[] args) {
//创建runnable的对象
TestThread3 testThread3 = new TestThread3();
//创建一个thread对象
new Thread(testThread3).start();