线程
普通方法调用和多线程
Process和Thread
- 程序是指令和数据的有序集合,是静态概念
- 进程Process是执行程序的一次执行过程,是一个动态的概念,是系统资源分配的单位
- 通常一个进程中可以包含多个线程,每个进程中至少有一个线程,线程是CPU调度和执行的单位
核心概念
- 线程是独立的执行路径
- 程序运行时,即使没有自己创建线程,后台也会有多个线程,如主线程,gc线程(清理)
- main()称为主线程,是系统的入口,用于执行整个程序
- 一个进程中,如开辟了多个线程,线程的运行由调度器安排
- 对一份资源进行操作时,会存在资源抢夺的问题,需要加入并发控制
- 线程会带来额外的开销,如CPU调度时间,并发控制开销
- 每个线程在自己的工作内存交互,内存控制不当会造成数据不一致
线程创建
Thread类(重点)
- 自定义线程类继承Thread类
- 重写run()方法,编写线程执行体
- 创建线程对象,调用start()方法开启线程
package OOP.Demo;
/**
* @version: java version 1.8
* @Author: 14
*/
public class Thread01 extends Thread{
//创建线程方式一: 继承Thread类,重写run方法,调用start开启线程
//总结:线程开启不一定立即执行,由CPU调度
@Override
public void run() {//重写run方法
for (int i = 0; i <500 ; i++) {
System.out.println("这里是线程01");
}
}
public static void main(String[] args) {//main线程,主线程
//创建线程对象
Thread01 t1 = new Thread01();
//调用start();开启线程
t1.start();
for (int i = 0; i < 1000; i++) {
System.out.println("这里是main");
}
}
}
例子:下载图片测试
package OOP.Demo;
import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.IOException;
import java.net.URL;
/**
* @version: java version 1.8
* @Author: 14
*/
public class Thread02 extends Thread{
private String Url;
private String path;
public Thread02(String Url,String path){
this.Url = Url;
this.path = path;
}
@Override
public void run() {
new WebDownloader().downloader(Url,path);
// WebDownloader webDownloader = new WebDownloader();
// webDownloader.downloader(Url,path);
System.out.println("下载了文件在:"+path);
}
public static void main(String[] args) {
Thread02 t1 = new Thread02("/i/l/?n=24&i=blog/3475380/202407/3475380-20240701154652288-1747217106.png","1.png");
Thread02 t2 = new Thread02("/i/l/?n=24&i=blog/3475380/202407/3475380-20240701154705043-664732010.png","2.png");
Thread02 t3 = new Thread02("/i/l/?n=24&i=blog/3475380/202407/3475380-20240701154710607-423679454.png","3.png");
t1.start();
t2.start();
t3.start();
}
}
class WebDownloader{
public void downloader(String url,String path){
try {
FileUtils.copyURLToFile(new URL(url),new File(path));
} catch (IOException e) {
e.printStackTrace();
System.out.println("IOException");
}
}
}
Runnable接口(重点)
-
定义MyRunnable类实现Runnable接口
-
实现run()方法,编写线程执行体
-
创建线程对象,调用start()方法启动线程
推荐使用Runnable对象,因为Java单继承的局限性
package OOP.Demo;
/**
* @version: java version 1.8
* @Author: 14
*/
public class Thread03 implements Runnable{
@Override
public void run() {
for (int i = 0; i <500 ; i++) {
System.out.println("这里是线程01");
}
}
public static void main(String[] args) {//main线程,主线程
//创建线程对象
Thread03 t1 = new Thread03();
//调用start();开启线程
new Thread(t1).start();//区别在这
for (int i = 0; i < 1000; i++) {
System.out.println("这里是main");
}
}
}
例子:购买火车票
package OOP.Demo;
/**
* @version: java version 1.8
* @Author: 14
*/
//多个线程同时操作一个对象
//买火车票例
//发现问题:多个线程操作同一个资源,线程不安全,数据紊乱
public class Thread04 implements Runnable{
//票数
private int ticketNums = 10;
@Override
public void run() {
while (true) {
if(ticketNums>0){
System.out.println(Thread.currentThread().getName()+"->拿到了第"+ticketNums--+"票");
}else {
break;
}
//模拟延时
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
Thread04 t4 = new Thread04();
new Thread(t4,"小红").start();
new Thread(t4,"小米").start();
new Thread(t4,"万恶的黄牛").start();
}
}
例子:龟兔赛跑
package OOP.Demo;
/**
* @version: java version 1.8
* @Author: 14
*/
public class Race implements Runnable{
static String winner = null;
@Override
public void run() {
for (int i = 0; i <= 100; i++) {
if (Thread.currentThread().getName().equals("兔子") && i%11 == 0) {
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if (winner(i)){
break;
}
System.out.println(Thread.currentThread().getName() + "跑了" + i + "步");
}
}
public boolean winner(int steps){
if(winner != null){
return true;
}
if(steps >= 100){
winner = Thread.currentThread().getName();
System.out.println("胜者是:" + winner);
return true;
}
return false;
}
public static void main(String[] args) {
Race race = new Race();
new Thread(race,"兔子").start();
new Thread(race,"乌龟").start();
}
}
Callable接口
-
实现Callable接口,需要返回值类型
-
重写call()方法,需要抛出异常
-
创建目标对象
-
创建执行服务:
ExecutorService ser = Executors.newFixedThreadPool(1);
-
提交执行:
Future<Boolean> result = ser.submit(t1);
-
获取结果:
boolean r = result.get();
-
关闭服务:
ser.shutdownNow();
例子:利用Callable改造下载图片案例
package OOP.Demo;
import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.concurrent.*;
/**
* @version: java version 1.8
* @Author: 14
*/
public class Thread05 implements Callable<Integer> {
private String Url;
private String path;
public Thread05(String Url,String path){
this.Url = Url;
this.path = path;
}
@Override
public Integer call() {
new WebDownloader().downloader(Url,path);
// WebDownloader webDownloader = new WebDownloader();
// webDownloader.downloader(Url,path);
System.out.println("下载了文件在:"+path);
return 0;
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
Thread05 t1 = new Thread05("/i/l/?n=24&i=blog/3475380/202407/3475380-20240701154652288-1747217106.png","1.png");
Thread05 t2 = new Thread05("/i/l/?n=24&i=blog/3475380/202407/3475380-20240701154705043-664732010.png","2.png");
Thread05 t3 = new Thread05("/i/l/?n=24&i=blog/3475380/202407/3475380-20240701154710607-423679454.png","3.png");
// t1.start();
// t2.start();
// t3.start();
//创建服务
ExecutorService ser = Executors.newFixedThreadPool(3);
//提交执行
Future<Integer> f1 = ser.submit(t1);
Future<Integer> f2 = ser.submit(t2);
Future<Integer> f3 = ser.submit(t3);
//获取结果
Integer r1 = f1.get();
Integer r2 = f2.get();
Integer r3 = f3.get();
//打印结果
System.out.println(r1);
System.out.println(r2);
System.out.println(r3);
//关闭服务
ser.shutdownNow();
}
}
//class WebDownloader{
// public void downloader(String url,String path){
// try {
// FileUtils.copyURLToFile(new URL(url),new File(path));
// } catch (IOException e) {
// e.printStackTrace();
// System.out.println("IOException");
// }
// }
//}
Lambda表达式
-
函数式接口:
任何接口,如果只包含唯一的一个抽象方法,那么它就是函数式接口
public interface Runnable{ public abstract void run(); }
-
对于函数式接口,我们可以通过lambda表达式来创建该接口的对象
package OOP.Demo;
/**
* @version: java version 1.8
* @Author: 14
*/
public class LambdaTest {
//3、静态内部类
static class ILove1 implements Love{
@Override
public void love() {
System.out.println("I LOVE -->1");
}
}
public static void main(String[] args) {
//4、局部内部类
class ILove2 implements Love{
@Override
public void love() {
System.out.println("I LOVE -->2");
}
}
ILove iLove3 = new ILove();
//5、匿名内部类
iLove3 = new ILove(){
@Override
public void love() {
System.out.println("I LOVE -->3");
}
};
//6、Lambda表达式
Love iLove4 = ()-> { System.out.println("I LOVE -->4"); };
ILove iLove = new ILove();
ILove1 iLove1 = new ILove1();
ILove2 iLove2 = new ILove2();
iLove.love();
iLove1.love();
iLove2.love();
iLove3.love();
iLove4.love();
}
}
//1、定义函数式接口
interface Love {
void love();
}
//2、实现类
class ILove implements Love{
@Override
public void love() {
System.out.println("I LOVE -->0");
}
}
Lambda简化
总结
- lambda表达式只有一行代码的情况下,才能简化为一行,如有多行,需要花括号包裹
- 使用lambda表达式的前提是 接口为函数式接口
- 多个参数也可以去掉参数类型(要去就都去掉),用括号包裹
package OOP.Demo;
/**
* @version: java version 1.8
* @Author: 14
*/
public class LambdaTest {
public static void main(String[] args) {
//Lambda表达式
Love iLove = ()-> { System.out.println("I LOVE -->0"); };
//Lambda简化
Love1 iLove1 = a -> System.out.println("I LOVE -->" + a);
Love2 iLove2 = (a,b) -> {
System.out.println("I LOVE -->" + a);
System.out.println("I LOVE -->" + b);
};
iLove.love();
iLove1.love1(1);
iLove2.love2(2,3);
}
}
//1、定义函数式接口
interface Love {
void love();
}
interface Love1{
void love1(int a);
}
interface Love2{
void love2(int a, int b);
}
静态代理模式(线程的底部原理)
总结:
-
真实对象和代理对象都要实现同一个接口
-
代理对象必须要代理真实对象
好处:
-
代理对象可以做很多真实对象做不了的事情
-
真实对象专注做自己的事情
package OOP.Demo;
/**
* @version: java version 1.8
* @Author: 14
*/
public class StaticProxy {
public static void main(String[] args) {
Person person = new Person();
MarryCompany marryCompany = new MarryCompany(person);
marryCompany.marry();
//线程启动,也相当与静态代理
new Thread(()-> System.out.println("这是一个线程")).start();
new MarryCompany(new Person()).marry();
}
}
interface Marry{
void marry();
}
class Person implements Marry{
@Override
public void marry() {
System.out.println("找到漂亮老婆结婚啦!!!");
}
}
class MarryCompany implements Marry{
Person person;
public MarryCompany(Person person) {
this.person = person;
}
@Override
public void marry() {
before();
person.marry();
after();
}
public void before(){
System.out.println("婚庆人员在布置现场");
}
public void after(){
System.out.println("婚礼结束了,打钱");
}
}
标签:void,System,线程,println,new,public
From: https://www.cnblogs.com/shisi2001/p/18282735