线程的三种创建方式
1.继承Thread类
例子1
// 创建方式一:继承Thread类,重写run()方法 调用start开启线程
public class TestThread01 extends Thread{
@Override
public void run() {
for (int i = 0; i < 20; i++) {
System.out.println("我在看代码"+i);
}
}
public static void main(String[] args) {
//main线程 主线程
//创建一个线程对象
TestThread01 testThread01 = new TestThread01();
//调用start开启线程
testThread01.start();
for (int i = 0; i < 2000; i++) {
System.out.println("我在学习多线程"+i);
}
}
}
调用start()线程之间交替执行
调用run()和start()的区别
例子2:
//实现多线程同步下载图片
public class TestThread02 extends Thread{
private String url;
private String name;
public TestThread02(String url,String name){
this.url = url;
this.name = name;
}
//下载图片线程的执行体
@Override
public void run() {
TestThread02 t1 = new TestThread02("https://t7.baidu.com/it/u=4240641596,3235181048&fm=193&f=GIF", "1.jpg");
TestThread02 t2 = new TestThread02("https://t7.baidu.com/it/u=1951548898,3927145&fm=193&f=GIF", "2.jpg");
TestThread02 t3 = new TestThread02("https://t7.baidu.com/it/u=1831997705,836992814&fm=193&f=GIF", "3.jpg");
t1.start();
t2.start();
t3.start();
}
}
class WebDownLoader{
public void downloader(String url,String name){
try {
FileUtils.copyURLToFile(new URL(url),new File(name));
} catch (IOException e) {
e.printStackTrace();
}
}
}
2.实现Runnable接口
//创建线程方式二:实现runnable接口,重写run方法
public class TestThread03 implements Runnable {
@Override
public void run() {
for (int i = 0; i < 20; i++) {
System.out.println("我在看代码"+i);
}
}
public static void main(String[] args) {
//main线程 主线程
//创建runnable接口的实现类对象
TestThread03 testThread03 = new TestThread03();
//创建线程对象,通过线程对象来开启线程,代理
Thread thread = new Thread(testThread03);
thread.start();
for (int i = 0; i < 100; i++) {
System.out.println("我在学习多线程"+i);
}
}
}
多个线程同时操作同一个对象 买火车票的例子
//发现问题:多个线程操作同一个资源的情况下线程不安全,数据紊乱, 不同的人可以拿到同一张票(看打印结果)
public class TestThread04 implements Runnable{
private int ticketNums = 10;
@Override
public void run() {
while (true){
if (ticketNums <= 0){
break;
}
try {
Thread.sleep(200);//模拟延时
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"-->拿到了第"+ticketNums--+"票");
}
}
public static void main(String[] args) {
TestThread04 testThread04 = new TestThread04();
new Thread(testThread04,"小明").start();
new Thread(testThread04,"老师").start();
new Thread(testThread04,"黄牛党").start();
}
}
上述线程存在不安全性,想要线程安全请看另一篇博客 :线程同步安全
3.实现Callable接口
/线程创建方式三:实现callable接口
//可以定义返回值
//可以抛出异常
public class TestThread05 implements Callable<Boolean> {
private String url;
private String name;
public TestThread05(String url,String name){
this.url = url;
this.name = name;
}
//下载图片线程的执行体
@Override
public Boolean call() throws Exception {
WebDownLoader webDownLoader = new WebDownLoader();
webDownLoader.downloader(url,name);
System.out.println("下载了文件名为:"+name);
return true;
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
TestThread05 t1 = new TestThread05("https://t7.baidu.com/it/u=4240641596,3235181048&fm=193&f=GIF", "1.jpg");
TestThread05 t2 = new TestThread05("https://t7.baidu.com/it/u=1951548898,3927145&fm=193&f=GIF", "2.jpg");
TestThread05 t3 = new TestThread05("https://t7.baidu.com/it/u=1831997705,836992814&fm=193&f=GIF", "3.jpg");
//创建执行服务
ExecutorService executorService = Executors.newFixedThreadPool(3);
//提交执行
Future<Boolean> r1 = executorService.submit(t1);
Future<Boolean> r2 = executorService.submit(t2);
Future<Boolean> r3 = executorService.submit(t3);
//获取结果
Boolean rs1 = r1.get();
Boolean rs2 = r2.get();
Boolean rs3 = r3.get();
System.out.println(rs1);
System.out.println(rs2);
System.out.println(rs3);
//关闭服务
executorService.shutdownNow();
}
}
注意:线程开启不一定立即执行,由CPU调度执行