一、什么是线程 每个java程序都至少有一个线程,在学习线程之前我们的大部分程序都是单线程的,程序从main开始执行,一次向下执行每条代码,要是执行的过程中遇到阻塞,程序就会停滞。基本上所有的操作系统都能同时运行多个任务,而通常每个任务就是一个程序,每个程序就是一个进程。当一个程序运行时,内部可能包含多个顺序执行流(基本上互补影响),我们把这样的每个顺序执行流叫线程。
二、线程和进程
一个任务通常包含一条进程。当每个程序进入内存运行时,即变成一个进程。进程是运行中的程序,特点;
独立性:进程是独立存在的,拥有独立的资源,如地址空间,内存等。
动态性:程序与进程的区别在于,程序是静态指令的集合,而进程是正在执行的指令集合
并发性:多个进程之间一般可以并发执行,多个进程之间不会互相干扰
线程是进程的做成部分,一个进程可以拥有多个线程,线程也被叫做轻量级的进程,线程是进程的执行单元。线程是独立运行的,和进程中的其他线程不互相影响,对于线程的执行是通过优先级来进行的,优先级相同的进程的执行是抢占式的,也就是说在优先级相同的情况下,任何一个正在执行过的线程都有可能被挂起,以能够执行其它的线程。
三、多线程的优点
由于进程都拥有独立的内存,而多个线程是共享内存的,可以提高极大的程序运行的效率。比如,一个浏览器必须能同时下载过个资源。
四、线程的创建和启动
1、继承Thread类创建线程
定义Thread类的子类,并重写该类的run()方法,该run()方法的方法体就是代表了线程需要执行的内容。我们经常把run()方法称为线程的执行体。创建Thread子类的对象,用线程对象的start()方法来启动线程
public class ThreadDemo extends Thread {
private String rootDirName;
// 主函数
public static void main(String[] args) {
// 得到系统根目录的个数
File[] dirFile = File.listRoots();
// 根据根目录的个数创建统计线程对象并启动
for (int i = 0; i < dirFile.length; i++) {
// 创建线程对象
ThreadDemo demo = new ThreadDemo(dirFile[i].getAbsolutePath());
demo.start();
try {
demo.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(dirFile[i].getAbsolutePath());
}
}
/**
* 统计某个磁盘文件数量的线程类
*
* @param root根目录的名字
*/
public ThreadDemo(String path) {
this.rootDirName = path;
}
/**
* 线程执行入口
*/
public void run() {
System.out.println("-------执行------->");
long start = System.currentTimeMillis();
int fileCount = countDir(rootDirName);
long time = System.currentTimeMillis();
}
/**
* 计算一个目录下所有文件的长度
*
* @param dir目录名
* @return 文件总长度
*/
public int countDir(String path) {
int count = 0;
File file = new File(path);
// 列出目录
File[] subFile = file.listFiles();
if (subFile == null || subFile.length == 0) {
return count;
}
for (int i = 0; i < subFile.length; i++) {
if (subFile[i].isDirectory()) {
count += countDir(subFile[i].getAbsolutePath());
}
if (subFile[i].isFile()) {
count++;
System.out.println(subFile[i].getAbsolutePath());
}
}
return count;
}
}
2、实现Runnable接口创建线程对象
定义Runnable接口的实现类,重写该类的run方法,该run方法的方法体同样是该线程的线程执行体,创建Runnable实现类的实例,并以此实例作为Thread类的传入参数创建Thread类对象,该Thread类对象才是真正的线程对象。
import java.lang.Runnable;
public class RunnableDemo implements Runnable {
private int i;
/**
* 构造方法
*/
public RunnableDemo(int i) {
this.i = i;
}
/**
* 主函数
*
* @param args
*/
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
// 实例化对象
RunnableDemo demo = new RunnableDemo(i);
Thread thread = new Thread(demo);
// 启动线程
thread.start();
// try {
// thread.sleep(2000);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
}
}
/**
* 实现Runnable抽象类的方法
*/
public void run() {
// 循环输出
while (true) {
long time = System.currentTimeMillis();
System.out.println(i+"号线程"+time);
}
}
}
3、以内部类的形式创建线程
可以在一个方法中创建线程,当方法被调用时线程启动
public void startMyThread() {
Runnable runner = new Runnable() {
public void run() {
while (true) {
try {
Thread.sleep(3000);
otherMethod(id);
} catch (Exception e) {
}
}
}
};
Thread thread = new Thread(runner);
thread.start();
}
private void otherMethod(int i) {
System.out.println("调用类中的其他方法" + i);
}
五、线程的应用
线程游戏:利用线程我们能够做些小游戏,我们小组选择的是放水果忍者
进入游戏
各个模式的游戏画面