创建多线程有三种方法:第一种是继承Thread类+重写run方法,第二种实现Runnable接口+重写run方法,第三种实现Collection接口。多用第二种,少用 第一种,第三种基本不用。
第一种方法:继承Thread
首先创建一个类StartThread01 继承Thread类,重写run方法,然后在main方法启动线路,先创建子类对象,然后调用子类对象的start方法启动线程,由cpu安排时间片调用,不保证立即运行。
启动线程要用start()方法。当用start()开始一个线程后,线程就进入就绪状态,使线程所代表的虚拟处理机处于可运行状态,这意味着它可以由JVM调度并执行。这并不意味着线程就会立即运行。当cpu分配给它时间时,才开始执行run()方法(如果有的话)。START()是构造方法,它调用RUN()方法.而RUN()方法是你必须重写的. run()方法中包含的是线程的主体。在Java中要实现线程,最简单的方式就是扩展Thread类,重写其中的run方法,Thread类中的run方法本身并不执行任何操作,如果我们重写了run方法,当线程启动时,它将执行run方法。
package com.cb.thread;
/*
* 创建线程方式一:
* 1、创建:继承Thread+重写run
* 2、启动:创建子类对象 + start
*/
public class StartThread01 extends Thread {
//线程入口点
@Override
public void run() {
for (int i = 0; i < 20; i++) {
System.out.println("一边敲代码!!!");
}
}
public static void main(String[] args) {
//创建子类对象
StartThread01 st = new StartThread01();
//启动线路
st.start(); //不保证立即运行cpu调用
//普通方法调用
//st.run();
for (int i = 0; i < 20; i++) {
System.out.println("一边听歌!!!");
}
}
}
分析一下以上代码:先从main进来,然后创建子类对象,然后调用子类的start方法开启线程,交给cpu去调,这时候程序不会等它回来,往下直接运行,这时候就相当于两条线路,可以一边敲代码一边听歌。如果把start方法改run方法那就成了普通方法调用,那就只能先敲完代码才能听歌,这就是一条路。如果把一边听歌的这个循环放在start方法前面,那就必须把听歌的这个循环打印完才启动线程。
以下案例,启动三个线程,下载三张图片
package com.cb.thread;
public class TDownloader extends Thread {
private String url; //图片地址
private String name; //存储名字
public TDownloader(String url,String name) {
this.url = url;
this.name = name;
}
@Override
public void run() {
WebDownloader wd = new WebDownloader();
wd.downloader(url, name);
}
public static void main(String[] args) {
TDownloader td1 = new TDownloader("http://pic1.win4000.com/wallpaper/c/579f1942850a7.jpg", "杨洋");
TDownloader td2 = new TDownloader("http://file06.16sucai.com/2016/0420/faa06f4f0566466e800885110a56cc32.jpg", "婴儿");
TDownloader td3 = new TDownloader("https://pic.sogou.com/pics/recompic/detail.jsp?category=%E6%98%8E%E6%98%9F&tag=%E5%90%B4%E4%BA%A6%E5%87%A1#33%2617313718", "吴亦凡");
td1.start();
td2.start();
td3.start();
}
}