程序.进程(Process).线程(Thread)
在操作系统中运行的程序就是进程,程序是代码,是死的,是一个静态的概念,而进程是执行程序的一次执行过程,是一个动态的概念,是系统资源分配的单位,比如QQ,LOL,IDE等等。。
一个进程可以有多个线程,如在看视频时,可以同时听声音,看图像,看弹幕,等等。
即使一个进程什么都不干,里面也有一个main线程(主线程) ,线程就是独立的执行路径。
注意:很多多线程是模拟出来的,真正的多线程是只有多个CPU,即多核,如 服务器。而模拟出来的多线程在一个CPU下,同一时间只执行一个代码,只是切换的很快而已。
创建线程之一:
继承Thread (不建议使用,避免OOP单继承局限性)
- 自定义线程类继承Thread类
- 重写run()方法,编写线程执行体
- 创建线程对象,调用start()方法启动线程
实例如下:
public class TestThread1 extends Thread {
@Override
public void run() {
super.run();
//run方法线程体
for (int i = 0; i < 20; i++) {
System.out.println("run线程。。。。");
}
}
public static void main(String[] args) {
//main线程,主线程
//创建线程对象,调用start方法开启线程
TestThread1 testThread1 = new TestThread1();
testThread1.start();
for (int i = 0; i < 200; i++) {
System.out.println("main......");
}
}
}
注意:线程开启不一定立即执行,由cpu调度执行。调用多个线程对象的start()方法,执行顺序是不一定的。
用多线程下载图片
下载一个commons IO包,他是别人针对开发IO流功能的工具类库,直接百度搜索即可,将其拷到项目里的一个新建文件夹里,此时他不能直接用,要右键此文件夹选中Add as Library添加到库里面。此时如果查看项目资源目录,里面就有一个libraries。
1.先写一个下载器,里面有一个下载方法,它是通过FileUtils这个工具类的copyURLToFile方法将图片下载下来。
//下载器,因为这个定义的类全都放在了一个页面所以没有public,一个java类中只能有一个public class类
class WebDownLoader{
public void downLoader(String url,String name){
try {
FileUtils.copyURLToFile(new URL(url), new File(name));//此方法是把网络上的一个网页地址变成一个文件
}catch (IOException e){
e.printStackTrace();
System.out.println("IO异常,dowmloader方法出现问题");
}
}
}
2.要实现一个线程类,然后写一个有参构造,用来丢入地址和名字,再然后重写run()方法,它是下载图片线程的执行体。最后在main()函数中通过三个构造器创建三个线程,然后用三个start()方法把这三个线程同时启动起来。
public class TextThread2 extends Thread{
private String url;//网络图片地址
private String name;//保存的文件名
public TextThread2(String url,String name){ //写构造器
this.url=url;
this.name=name;
}
@Override
public void run() {
WebDownLoader webDownLoader = new WebDownLoader();
webDownLoader.downLoader(url,name);
System.out.println("下载了文件名为:"+name);
}
public static void main(String[] args) {
TextThread2 t1=new TextThread2("此处写要下载图片的地址","给想要下载的图片命名");
TextThread2 t2=new TextThread2("此处写要下载图片的地址","给想要下载的图片命名");
TextThread2 t3=new TextThread2("此处写要下载图片的地址","给想要下载的图片命名");
t1.start();
t2.start();
t3.start();
}
}
创建线程方法二:
实现Runnable(推荐该方式)可避免单继承局限性,灵活,方便同一个对象被多个线程使用
- 定义MyRunnable类实现Runnable接口
- 重写run()方法,编写线程执行体
- 创建线程对象,调用start()方法启动线程
实例如下:
和继承Thread类那种方法差不多,这就是将Runable接口的实现类对象丢入Thread里面,调用start()启动.
public class TextThread3 implements Runnable {
@Override
public void run() {
//run()方法线程体
for (int i = 0; i < 200; i++) {
System.out.println("run"+i);
}
}
public static void main(String[] args) {
//创建runnable接口的实现类对象
TextThread3 textThread3 = new TextThread3();
//创建线程对象,通过线程对象来开启我们的线程,代理
Thread thread = new Thread(textThread3);
thread.start();
//这两句等价于 new Thread(testThread3).start();
for (int i = 0; i < 1000; i++) {
System.out.println("main"+i);
}
}
}
用runnable多线程下载图片
和第一种方式比较只需改动两处——画“***************************”处
public class TextThread2 implements Runnable{ ***************************************
private String url;//网络图片地址
private String name;//保存的文件名
public TextThread2(String url,String name){ //写构造器
this.url=url;
this.name=name;
}
@Override
public void run() {
WebDownLoader webDownLoader = new WebDownLoader();
webDownLoader.downLoader(url,name);
System.out.println("下载了文件名为:"+name);
}
public static void main(String[] args) {
TextThread2 t1=new TextThread2("此处写要下载图片的地址","给想要下载的图片命名");
TextThread2 t2=new TextThread2("此处写要下载图片的地址","给想要下载的图片命名");
TextThread2 t3=new TextThread2("此处写要下载图片的地址","给想要下载的图片命名");
new Thread(t1).start(); **************************************
new Thread(t2).start(); **************************************
new Thread(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();
System.out.println("IO异常,dowmloader方法出现问题");
}
}
}
一个对象被多个线程使用的实例:
//多个线程同时操作一个Runnable接口的对象
//买火车票的例子
public class TestThread4 implements Runnable{
//票数
private int ticketNums = 10;
@Override
public void run() {
while(true){
if(ticketNums<=0){
break;
}
//模拟延时,200毫秒,0.2秒
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"拿到了"+ticketNums--+"票");
}
}
public static void main(String[] args) {
//一个资源
TestThread4 testThread4 = new TestThread4();
//多个代理
new Thread(testThread4,"小红").start();
new Thread(testThread4,"小白").start();
new Thread(testThread4,"小黑").start();
}
}
多线程龟兔赛跑
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(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
boolean flag = gameOver(i);
if (flag) {
break;
}
System.out.println(Thread.currentThread().getName() + "跑了" + i + "步");
}
}
//判断是否完成比赛
private boolean gameOver(int steps) {
//判断是否有胜利者
if (winner != null) {
return true;
} else if (steps >= 100) {
//Thread.currentThread()这是Theard类的currentThread()方法,意思就是”当前线程“
winner = Thread.currentThread().getName();
System.out.println("winner is" + winner);
return true; }
else {
return false;
}
}
public static void main(String[] args) {
Race race = new Race();
//由于两个线程公用一个资源,都用run方法,谁先跑完执行方法里面的break,另一个也就跑不了了
new Thread(race,"兔子").start();
new Thread(race,"乌龟").start();
}
}
Callable下载图片(了解)