重点:
-
线程的实现
-
线程的同步
Process(进程)和 Thread(线程)
进程中有线程,真正执行的是线程
线程的创建
- Thread class (重点) 继承Tread类
- Runnable 接口 (重点) 实现Runnable接口
- Callable 接口 (了解)
1.继承Tread类:
1.继承Thread类
2.重写run()方法
3.创建对象,调用start()来启动
public class ThreadDemo01 extends Thread {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("我在学习多线程---"+i);
}
}
public static void main(String[] args) {
ThreadDemo01 threadDemo01 = new ThreadDemo01();
threadDemo01.start();
for (int i = 0; i < 100; i++) {
System.out.println("我在涨知识---"+i);
}
}
}
结果为:

总结:线程开启不一定会执行没做过是有cpu来调度执行的
练习:下载网图
public class TestThread extends Thread {
private String url ;
private String name;
public TestThread(String url,String name){
this.name=name;
this.url=url;
}
@Override
public void run() {
WebDownLoader webDownLoader = new WebDownLoader();
webDownLoader.downLoad(url,name);
System.out.println("下载了文件为:"+name+"文件的URL为:"+url);
}
public static void main(String[] args) {
TestThread t1 = new TestThread("http://www.pppnut.cn/blog-image/study-DesignPattern/Factory/1.jpg","1.jpg");
TestThread t2 = new TestThread("http://www.pppnut.cn/blog-image/study-DesignPattern/Factory/2.jpg","2.jpg");
TestThread t3 = new TestThread("http://www.pppnut.cn/blog-image/study-DesignPattern/Factory/3.jpg","3.jpg");
t1.start();
t2.start();
t3.start();
}
}
//下载器
class WebDownLoader{
//下载方法
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异常,downLoad方法出现问题");
}
}
}
结果:

2.实现Runnable接口
1.实现Runnable接口
2.重写run()方法
3.创建实现对象,创建代理对象,调用start()方法
package com.summer.Thread;
public class ThreadDemo03 implements Runnable {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("我在学习多线程---"+i);
}
}
public static void main(String[] args) {
// 创建实现对象
ThreadDemo03 threadDemo03 = new ThreadDemo03();
// 创建代理对象
Thread thread = new Thread(threadDemo03);
// 调用start()方法启动线程
thread.start();
for (int i = 0; i < 100; i++) {
System.out.println("我在涨知识---"+i);
}
}
}
总结:runable接口来实现多线程,需要将实现对象丢入Thread中进行代理
为是什么会Thread有代理?为什么会用runable接口来实现?
应为runable是一个接口,其中只定义了一个run()方法,我们对run()进行了重写,但是我们就光靠一个run()方法是没有办法启动我们的线程的这个时候就要借助Thread中start()方法。所以就会出现上面的将runable实现类丢给了Thread。这样的做的话我们还可以吧这个runable丢给其他的类,去实现其他的功能。
runable避免了oop单继承的局限性,灵活,方便同一个对象被多个线程使用。
练习
1.抢票案例
public class ThreadDemo04 implements Runnable {
private int ticketNum = 10;
@Override
public void run() {
while (true){
if(ticketNum<=0){
break;
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"拿到第"+ticketNum--+"票");
}
}
public static void main(String[] args) {
ThreadDemo04 threadDemo04 = new ThreadDemo04();
new Thread(threadDemo04,"小明").start();
new Thread(threadDemo04,"老师").start();
new Thread(threadDemo04,"黄牛").start();
}
}`
结果:

问题:多个线程同时操作同一个资源,会造成资源的紊乱。
1.龟兔赛跑的案例
package com.summer.Thread;
public class ThreadTestRace implements Runnable {
private String winner;
@Override
public void run() {
if (Thread.currentThread().getName().equals("兔子")){
for (int i = 0; i <= 500; i=i+10) {
if (i%120==0){
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if (gameOver(i)){
System.out.println("获胜者是"+winner);
break;
}else {
System.out.println(Thread.currentThread().getName()+"走了"+i+"步数");
}
}
}else {
for (int i = 0; i <= 500; i++) {
if (gameOver(i)){
System.out.println("获胜者是"+winner);
break;
}else {
System.out.println(Thread.currentThread().getName()+"走了"+i+"步数");
}
}
}
}
public boolean gameOver(int step){
if(winner!=null){
return true;
}else if(step>=500){
winner = Thread.currentThread().getName();
return true;
}
return false;
}
public static void main(String[] args) {
ThreadTestRace threadTestRace = new ThreadTestRace();
new Thread(threadTestRace,"兔子").start();
new Thread(threadTestRace,"乌龟").start();
}
}
实现Callable接口(了解)
- 创建服务
- 提交线程
- 获取结果
- 获取结果
public class ThreadDemo05 implements Callable<Boolean> {
private String url ;
private String name;
public ThreadDemo05(String url,String name){
this.name=name;
this.url=url;
}
@Override
public Boolean call() throws Exception {
WebDownLoader webDownLoader = new WebDownLoader();
webDownLoader.downLoad(url,name);
System.out.println("下载了文件为:"+name+"文件的URL为:"+url);
return true;
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
ThreadDemo05 t1 = new ThreadDemo05("http://www.pppnut.cn/blog-image/study-DesignPattern/Factory/1.jpg","1.jpg");
ThreadDemo05 t2 = new ThreadDemo05("http://www.pppnut.cn/blog-image/study-DesignPattern/Factory/2.jpg","2.jpg");
ThreadDemo05 t3 = new ThreadDemo05("http://www.pppnut.cn/blog-image/study-DesignPattern/Factory/3.jpg","3.jpg");
//创建服务
ExecutorService ser = Executors.newFixedThreadPool(3);
//提交线程
Future<Boolean> r1 = ser.submit(t1);
Future<Boolean> r2 = ser.submit(t2);
Future<Boolean> r3 = ser.submit(t3);
//获取结果
Boolean res1 = r1.get();
Boolean res2 = r2.get();
Boolean res3 = r3.get();
//关闭线程池
ser.shutdown();
}
}
//下载器
class WebDownLoader{
//下载方法
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异常,downLoad方法出现问题");
}
}
}
callable 的好处:
- 可以定义返回值类型
- 可以抛出异常
静态代理模式
真实对象和代理对象都要实现同一个接口。
代理对象代理真实角色。
好处:
- 代理对象可以做很多真实对象做不了的事情
- 真实对象专注做自己的事情
网友评论