多线程
线程简介
程序:指令和数据的有序集合,其本身没有任何含义,是一个静态概念
进程:执行程序的一次执行过程,动态概念,是系统资源分配的基本单位
线程:通常一个进程可以包含若干个线程,线程是cpu调度和执行的单位
线程实现 (重点)
继承Thread类 (重点)
- 继承Thread类
- 重写run()
- 用start()调用
public class Main extends Thread{
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("run()" + i);
}
}
public static void main(String[] args) {
Main main = new Main();
main.start();//开启子线程,此时会交替执行
for (int i = 0; i < 100; i++) {
System.out.println("main()" + i);
}
}
}
例子:同时下载图片
public class TestThread extends Thread {
private String url;
private String fileName;
public TestThread(String url, String fileName){
this.url = url;
this.fileName = fileName;
}
@Override
public void run() {
DownloadPic down = new DownloadPic();
down.down(url, fileName);
System.out.println(fileName + "下载成功");
}
public static void main(String[] args) {
TestThread t1 = new TestThread("https://img.alicdn.com/tfs/TB1JHFR1.T1gK0jSZFrXXcNCXXa-320-560.jpg", "1.jpg");
TestThread t2 = new TestThread("https://img.alicdn.com/tfs/TB1JHFR1.T1gK0jSZFrXXcNCXXa-320-560.jpg", "2.jpg");
TestThread t3 = new TestThread("https://img.alicdn.com/tfs/TB1JHFR1.T1gK0jSZFrXXcNCXXa-320-560.jpg", "3.jpg");
//下载顺序由cpu调度
t1.start();
t2.start();
t3.start();
}
}
class DownloadPic{//下载图片的类
public void down(String url, String fileName){
try {
FileUtils.copyURLToFile(new URL(url), new File(fileName));//在common-io中
} catch (IOException e) {
e.printStackTrace();
System.out.println("下载异常");
}
}
}
实现Runnable接口(重点)
建议用此方法,因为Java是单继承
- 实现Runnable接口
- 重写run()
- 用start()调用
public class TestRun implements Runnable {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("run()" + i);
}
}
public static void main(String[] args) {
TestRun tRun = new TestRun();//在创建Thread时作为参数传递
new Thread(tRun).start();//开启子线程
for (int i = 0; i < 100; i++) {
System.out.println("main()" + i);
}
}
}
并发问题:会有不同的线程拿到同一张票
public class Bingfa implements Runnable {
private int count = 10;
@Override
public void run() {
while (true){
if (count <= 0){
break;
}
System.out.println(Thread.currentThread().getName() + "抢到了第" + count-- + "张票");
}
}
public static void main(String[] args) {
Bingfa bingfa = new Bingfa();
new Thread(bingfa, "小明").start();
new Thread(bingfa, "黄牛党").start();
new Thread(bingfa, "老师").start();
}
}
例子: 龟兔赛跑
public class Race implements Runnable {
private static String winner;
@Override
public void run() {
for (int i = 1; i <= 10; i++) {
//让兔子休眠
if (Thread.currentThread().getName().equals("兔子") && i % 2 == 0) {
try {
Thread.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
boolean win = getWin(i);
if (win) {
break;
}
System.out.println(Thread.currentThread().getName() + "跑了第" + i + "步");
}
}
public boolean getWin(int step) {
boolean flag = false;
if (winner != null) {//已经存在胜利者
flag = true;
}
if (step == 10) {
winner = Thread.currentThread().getName();
System.out.println(Thread.currentThread().getName() + "is a winner!");
flag = true;
}
return flag;
}
public static void main(String[] args) {
Race race = new Race();
new Thread(race, "兔子").start();
new Thread(race, "乌龟").start();
}
}
实现Callable接口(了解即可)
- 实现Callable接口,需要返回值类型
- 重写call(),需要抛出异常
- 创建目标对象
- 创建执行服务
- 提交执行
- 获取结果
- 关闭服务
例子:同时下载图片
public class TestCall implements Callable<Boolean> {//实现callable
private String url;
private String name;
public TestCall(String url, String name){
this.url = url;
this.name = name;
}
@Override
public Boolean call() throws Exception {//重写call()
DownloadPict down = new DownloadPict();
down.down(url, name);
System.out.println(name + "下载成功");
return true;
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
//创建执行服务
ExecutorService pool = Executors.newFixedThreadPool(3);
//提交执行
Future<Boolean> s1 = pool.submit(new TestCall("https://img.alicdn.com/tfs/TB1JHFR1.T1gK0jSZFrXXcNCXXa-320-560.jpg", "1.jpg"));
Future<Boolean> s2 = pool.submit(new TestCall("https://img.alicdn.com/tfs/TB1JHFR1.T1gK0jSZFrXXcNCXXa-320-560.jpg", "2.jpg"));
Future<Boolean> s3 = pool.submit(new TestCall("https://img.alicdn.com/tfs/TB1JHFR1.T1gK0jSZFrXXcNCXXa-320-560.jpg", "3.jpg"));
//获取结果
Boolean bs1 = s1.get();
Boolean bs2 = s2.get();
Boolean bs3 = s3.get();
//关闭执行
pool.shutdown();
System.out.println(bs1);
System.out.println(bs2);
System.out.println(bs3);
}
}
class DownloadPict{
public void down(String url, String name){
try {
FileUtils.copyURLToFile(new URL(url), new File(name));//在common-io.jar中
} catch (IOException e) {
e.printStackTrace();
System.out.println("下载异常");
}
}
}
如有不对的地方欢迎指出,共同进步!