方法调用和多线程
-
仅主线程一条执行路径
-
多条执行路径,主线程和子线程并行交替执行。
-
在操作系统中运行的程序就是进程,如QQ、播放器、游戏、IDE。
-
一个进程可以有多个线程,如视频中同时听声音,看图像,看弹幕等。
-
Process与Thread
-
程序是指令和数据的有序集合,其本身没有运行的含义,是一个静态的概念。
-
进程是执行程序的一次执行过程,它是一个动态的概念,是系统资源分配的单位。
-
一个进程中可以包含若干个线程,至少也有一个,线程是CPU调度和执行的单位。
-
真正的多线程:有多个CPU(多核),如服务器。
-
虚假的多线程:通过模拟获得,即在一个CPU的情况下,同一个时间点CPU只执行一个代码,但切换的速度很快,让人产生同时执行的错觉。
-
main函数就是主线程,其他均称子线程。
本章核心概念
-
线程就是独立的执行路径
-
在程序运行时即使没有自己创建线程,后台也会有多个线程,如 main 函数主线程和 gc 线程。
-
main() 称为主线程,是系统的入口,用于执行整个程序。
-
在一个进程中,如果开辟了多个线程,线程的运行会由调度器 (CPU) 安排调度,调度器与操作系统紧密相关,先后顺序不能人为干预。
-
对同一份资源操作时会存在资源抢夺的问题,需要加入并发控制。
-
线程会带来额外的开销,如CPU调度时间和并发控制开销。
-
每个线程在自己的工作内存中交互,内存控制不当会造成数据不一致的情况。
线程的创建
-
学习函数前要会看 JDK 帮助文档
-
自定义线程类继承Thread类
-
重写 run ( ) 方法,编写线程执行体。
-
创建线程对象,调用 start ( ) 方法启动线程。
-
package com.kuang.demo;
//创建线程方式一: 继承Thread类、重写run方法、调用start开启线程
public class StartThread extends Thread{
//线程入口点
@Override
public void run(){
//run方法线程体
for(int i=0; i < 20; i++){
System.out.println("lisening");
}
}
}
public static void main(String[] args){
//main主线程内创建线程对象
StartThread t = new StartThread();
//调用start方法开启线程,记住不是调用run方法!用start就会交替执行,是多线程的概念,用run就是顺序执行单线程了。
t.start();
}
-
线程开启过后不一定立即执行,由CPU安排调度,所以可能每次执行结果都不一样。
package com.kuang.demo;
import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.IOException;
import java.net.URL;
//练习 Thread 实现多线程同步下载图片
public class TestThread extends Thread{
private String url; //网络图片地址
private String name; //保存的文件名
//用构造器丢入两个参数,类初始化就直接用。
public TestThread(String url, String name){
this.url = url;
this.name = name;
}
@Override //run()方法就是下载图片线程的执行体
public void run(){
WebDownloader webDownloader = new WebDownloader();
webDownloader.downloader(url, name);
System.out.println("下载的文件名为:" + name);
}
public static void main(String[] args){
TestThread t1 = new TestThread("http://blog.kuangstudy.com/......", "why1.jpg");
TestThread t2 = new TestThread("http://blog.kuangstudy.com/......", "why2.jpg");
TestThread t3 = new TestThread("http://blog.kuangstudy.com/......", "why3.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();
System.out.println("IO异常,downloader方法出现问题");
}
}
}