process 进程 Thread 线程
执行程序的一次执行过程,他是一个动态的概念,可以有若干个线程,一个进程中可以包含若干个线程,同时一个进程中至少有一个线程,不然没有存在的意义(程序--进程--线程)main是主线程
线程
- 线程是对立形成的路径
- 在运行中,即便自己没有创建线程,后台也会有多个线程
- 线程的运行由调度器安排(CPU),先后顺序不能人为干预
- main是主线程
- 线程开启不一定会立即执行,由CPU调度执行
- 一个进程有多个线程
- 线程是独立的执行路径
- 先后顺序不能人为干预
- 进程-->线程
package demo01;
public class TestThread1 extends Thread{
//创建线程方式一:继承Thread类,重写run()方法,调用start开启线程
//线程开启不一立即执行,由CPU调度执行
//交替执行
@Override
public void run() {//重写run方法,run方法线程体
for (int i = 0; i < 20; i++) {
System.out.println("我在看代码----"+i);
}
}
//主方法 main线程
public static void main(String[] args) {
//创建一个线程对象
TestThread1 testThread1 = new TestThread1();
//调用start方法开始线程
testThread1.start();
//start()交替执行 run()先执行我在看代码
for (int i = 0; i < 20; i++) {
System.out.println("我在学习多线程----"+i);
}
}
}
package demo01;
import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.IOException;
import java.net.URL;
//练习Thread,实现多线程同时下载图片
public class TestThread2 extends Thread{
private String url;//网络图片地址
private String name;//保存文件名
private TestThread2(String url,String name){//有参构造
this.url = url;
this.name = name;
}
//下载图片线程执行体
@Override
public void run(){
WebDownloader webDownloader = new WebDownloader();//创建WebDownloader对象
WebDownloader.downloader(url,name);//传入url,name
System.out.println("下载的文件名为:"+name);
}
public static void main(String[] args) {
TestThread2 t1 = new TestThread2("https://img-blog.csdnimg.cn/20200109134240485.png","1.jpg");
TestThread2 t2 = new TestThread2("https://img-blog.csdnimg.cn/20200109134240485.png","2.jpg");
TestThread2 t3 = new TestThread2("https://img-blog.csdnimg.cn/20200109134240485.png","3.jpg");
//随机执行,谁先下载好先执行谁
t1.start();
t2.start();
t3.start();
}
}
//下载器
class WebDownloader{
//下载方法
public static void downloader(String url, String name){
try {
FileUtils.copyURLToFile(new URL(url),new File(name));
} catch (IOException e) {
e.printStackTrace();
System.out.println("I/O异常,downloade方法出现异常");
}
}
}
package demo01;
//创建线程方式3:实现runnable接口,重写run方法,执行线程需要丢人runnable接口实现类,调用start方法
public class TestThread3 implements Runnable{
public void run() {//重写run方法,run方法线程体
for (int i = 0; i < 20; i++) {
System.out.println("我在看代码----"+i);
}
}
//主方法 main线程
public static void main(String[] args) {
//创建runnbale接口的实现类对象
TestThread3 testThread3 = new TestThread3();
new Thread(testThread3).start();
for (int i = 0; i < 20; i++) {
System.out.println("我在学习多线程----"+i);
}
}
}
小结:
继承Thread类
- 子类继承Thread类具备多线程能力
- 启动线程:子类对象.start()
- 不建议使用:避免OOP单继承局限性
实现Runnable接口
- 实现接口Runnbale具有多线程能力
- 启动线程:传入目标对象+Thread对象.start()
- 推荐使用:避免单继承局限性,灵活方便,方便同一个对象被多个线程使用
线程并发问题
package demo01;
//多个线程同时操作同一个对象
//火车票问题
//发现问题:多个线程操作同一个资源情况下,线程不安全,数据混乱
public class TestThread4 implements Runnable{
//票数
private int ticketNums = 10;
//重写run方法
@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) {
TestThread4 ticket = new TestThread4();
//创建三个线程
new Thread(ticket,"小明").start();
new Thread(ticket,"老师").start();
new Thread(ticket,"黄牛党").start();
}
}
package demo01;
//模拟龟兔赛跑
public class Race implements Runnable{
//胜利者
private static String winner;
@Override
public void run() {
for (int i = 0; i <= 100; i++) {
//模拟兔子休息
if (Thread.currentThread().getName().equals("兔子")&& i%10==0){//每步休息一下
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//判断比赛是否结束
boolean flag = gamvOver(i);
//如果比赛结束就停止程序
if (flag){
break;
}
System.out.println(Thread.currentThread().getName()+"--> 跑了"+i+"步");
}
}
//判断是否完成比赛
private boolean gamvOver(int steps){
if (winner!=null){//已经有胜利者
return true;
}{
if (steps>=100){
winner = Thread.currentThread().getName();
System.out.println("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();
}
}
package demo02; import demo01.TestThread2; import org.apache.commons.io.FileUtils; import java.io.File; import java.io.IOException; import java.net.URL; import java.util.concurrent.*; public class TestCallable implements Callable{ private String url;//网络图片地址 private String name;//保存文件名 private TestCallable(String url,String name){//有参构造 this.url = url; this.name = name; } //下载图片线程执行体 //重写call方法 @Override public Boolean call(){//Boolean类型 WebDownloader webDownloader= new WebDownloader();//创建WebDownloader对象 WebDownloader.downloader(url,name);//传入url,name System.out.println("下载的文件名为:"+name); return true; } public static void main(String[] args) throws ExecutionException, InterruptedException { TestCallable t1 = new TestCallable("https://img-blog.csdnimg.cn/20200109134240485.png","1.jpg"); TestCallable t2 = new TestCallable("https://img-blog.csdnimg.cn/20200109134240485.png","2.jpg"); TestCallable t3 = new TestCallable("https://img-blog.csdnimg.cn/20200109134240485.png","3.jpg"); //创建执行服务 ExecutorService ser = Executors.newFixedThreadPool(3); //提交执行 Future r1 = ser.submit(t1); Future r2 = ser.submit(t2); Future r3 = ser.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); //关闭服务 ser.shutdownNow(); } } //下载器 class WebDownloader { //下载方法 public static void downloader(String url, String name) { try { FileUtils.copyURLToFile(new URL(url), new File(name)); } catch (IOException e) { e.printStackTrace(); System.out.println("I/O异常,downloade方法出现异常"); } } }



