注意:很多多线程是模拟出来的,真正的多线程是指有多个cpu,即多核,如服务器。如果是模拟出来的多线程,即在一个cpu的情况下,在同一时间点,cpu只能执行一个代码,因为切换的很快,所以就有同时执行的错局。
//创建线程方式之一: 继承Thread类 重写run方法 调用start开启线程
public class TestThreadDemo01 extends Thread{
@Override
public void run() {
//run方法线程体
for (int i = 0; i < 20; i++) {
System.out.println("我在学习多线程---"+i);
}
}
public static void main(String[] args) {
//main()线程 主线程
//创建一个线程对象
TestThreadDemo01 testThreadDemo01 = new TestThreadDemo01();
//调用start()方法开启线程
testThreadDemo01.start();//连个线程同时运行
//testThreadDemo01.run();//会按照先后顺序执行
for (int i = 0; i < 1000; i++) {
System.out.println("I like reading---"+i);
}
}
}
练习:实现网络图片下载
// 首先要下载commons-io-2.10.jar这个包才可以
import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.IOException;
import java.net.URL;
//练习Thread 实现多线程同时下载图片
public class TestThreadDemo02 extends Thread{
private String url;
private String name;
public TestThreadDemo02(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) {
TestThreadDemo02 threadDemo1 = new TestThreadDemo02("https://gimg2.baidu.com/image_search/src=http%3A%2F%2F2c.zol-img.com.cn%2Fproduct%2F124_500x2000%2F748%2FceZOdKgDAFsq2.jpg&refer=http%3A%2F%2F2c.zol-img.com.cn&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1626443878&t=bd893d4e852ae2792b563667c0146b21","1.jpg");
TestThreadDemo02 threadDemo2 = new TestThreadDemo02("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fpic11.nipic.com%2F20101209%2F4394820_003423992807_2.jpg&refer=http%3A%2F%2Fpic11.nipic.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1626444051&t=5c03a0e39a5982712edbb4559c6518dd","2.jpg");
TestThreadDemo02 threadDemo3 = new TestThreadDemo02("https://ss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=290629852,2245493184&fm=26&gp=0.jpg","3.jpg");
//同时进行 不分先后
threadDemo1.start();
threadDemo2.start();
threadDemo3.start();
}
}
//工具类 下载器
class WebDownloader{
//下载方法
public void downloader(String url,String name){
try {
FileUtils.copyURLToFile(new URL(url),new File(name));
} catch (IOException e) {
e.printStackTrace();
}
}
}
//创建线程方式2: 实现runnable接口,重写run方法,执行线程需要丢入runnable接口实现类,调用start开启线程
public class RunnableDemo01 implements Runnable{
@Override
public void run() {
//run方法线程体
for (int i = 0; i < 20; i++) {
System.out.println("我在学习多线程---"+i);
}
}
public static void main(String[] args) {
//创建runnable接口的实现类对象
RunnableDemo01 runnableDemo01 = new RunnableDemo01();
//创建线程对象,通过线程对象来开启我们的线程,代理
// Thread thread = new Thread(runnableDemo01);
// thread.start();
new Thread(runnableDemo01).start();//同时运行
for (int i = 0; i < 1000; i++) {
System.out.println("I like reading---"+i);
}
}
}
线程不安全实例:
//多个线程同时操作一个对象
//火车票的实例
//问题:多个线程同时操作一个对象,线程不安全,数据紊乱!
public class RunnableDemo02 implements Runnable {
private int ticketNum=10;
@Override
public void run() {
while (true){
if (ticketNum<=0){
break;
}
//模拟延时
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"-->拿到了第"+ticketNum--+"张票");
}
}
public static void main(String[] args) {
RunnableDemo02 runnableDemo02 = new RunnableDemo02();
new Thread(runnableDemo02,"小李子").start();
new Thread(runnableDemo02,"小郭子").start();
new Thread(runnableDemo02,"盗版").start();
}
}
多线程案例--龟兔赛跑:
//模拟龟兔赛跑
public class Race implements Runnable{
//胜利者
private static String winner;
@Override
public void run() {
for (int i = 0; i <= 1000; i++) {//i 表示步数
//模拟判断兔子休息 党每过10步且是兔子的时候 兔子就会休息
if (Thread.currentThread().getName().equals("兔子") && i%100==0){
try {
Thread.sleep(10);
} 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;
}{
if (steps>=1000){
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();
}
}
步骤如下:
实例演示下载图片:
import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.concurrent.*;
public class TestCallable implements Callable<Boolean> {
private String url;
private String name;
public TestCallable(String url, String name) {
this.url = url;
this.name = name;
}
//下载图片的线程体
@Override
public Boolean call() {
WebDownloader webDownloader = new WebDownloader();
webDownloader.downloader(url,name);
System.out.println("下载的图片是:"+name);
return true;
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
TestCallable threadDemo1 = new TestCallable("https://gimg2.baidu.com/image_search/src=http%3A%2F%2F2c.zol-img.com.cn%2Fproduct%2F124_500x2000%2F748%2FceZOdKgDAFsq2.jpg&refer=http%3A%2F%2F2c.zol-img.com.cn&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1626443878&t=bd893d4e852ae2792b563667c0146b21","4.jpg");
TestCallable threadDemo2 = new TestCallable("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fpic11.nipic.com%2F20101209%2F4394820_003423992807_2.jpg&refer=http%3A%2F%2Fpic11.nipic.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1626444051&t=5c03a0e39a5982712edbb4559c6518dd","5.jpg");
TestCallable threadDemo3 = new TestCallable("https://ss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=290629852,2245493184&fm=26&gp=0.jpg","6.jpg");
//1. 创建执行服务
ExecutorService ser= Executors.newFixedThreadPool(3);
//2. 提交执行
Future<Boolean> result1=ser.submit(threadDemo1);
Future<Boolean> result2=ser.submit(threadDemo2);
Future<Boolean> result3=ser.submit(threadDemo3);
//3. 获取结果
boolean r1=result1.get();
boolean r2=result2.get();
boolean r3=result3.get();
// 4. 关闭服务
ser.shutdownNow();
}
}
//工具类 下载器
class WebDownloader{
//下载方法
public void downloader(String url,String name){
try {
FileUtils.copyURLToFile(new URL(url),new File(name));
} catch (IOException e) {
e.printStackTrace();
}
}
}
Thread和Runnable比较:
原则:
//实例结婚模拟代理对象
public class ProxyStatic {
public static void main(String[] args) {
WeddingCompany weddingCompany = new WeddingCompany(new You());
weddingCompany.HappyMarry();
}
}
interface Marry{
void HappyMarry();
}
//真实角色 自己结婚
class You implements Marry{
@Override
public void HappyMarry() {
System.out.println("哈哈,灰太狼娶了美羊羊!!!");
}
}
//代理角色 帮助你结婚
class WeddingCompany implements Marry{
//设置要帮助的目标结婚对象
private Marry target;
public WeddingCompany(Marry target) {
this.target = target;
}
@Override
public void HappyMarry() {
before();
this.target.HappyMarry();//结婚
after();
}
private void before() {
System.out.println("结婚之前,先煮羊!!!");
}
private void after() {
System.out.println("结婚之后,开始吃羊!!!");
}
}
学习Lambda表达式是函数式接口的关键
函数式接口定义:
//推导lambda表达式
public class TestLambda01 {
//2.静态内部类实现
static class MyLambda2 implements ILambda{
@Override
public void show() {
System.out.println("Lambda表达式输出完毕!!!MyLambda2");
}
}
public static void main(String[] args) {
//1.外部类直接实现
ILambda lambda=new MyLambda1();//接口new实现类
lambda.show();
System.out.println("==================");
lambda=new MyLambda2();
lambda.show();
System.out.println("==================");
//3.局部内部类
class MyLambda3 implements ILambda{
@Override
public void show() {
System.out.println("Lambda表达式输出完毕!!!MyLambda3");
}
}
lambda=new MyLambda3();
lambda.show();
System.out.println("==================");
//4.匿名内部类 没有类的名称 必须借助接口或者父类
lambda=new ILambda() {
@Override
public void show() {
System.out.println("Lambda表达式输出完毕!!!MyLambda4");
}
};
lambda.show();
System.out.println("==================");
//5.简化Lambda表达式
lambda=()->{
System.out.println("Lambda表达式输出完毕!!!MyLambda5");
};
lambda.show();
}
}
//定义一个函数式接口
interface ILambda{
void show();
}
//接口实现类
class MyLambda1 implements ILambda{
@Override
public void show() {
System.out.println("Lambda表达式输出完毕!!!MyLambda1");
}
}
化简Lambda表达式:
//化简Lambda表达式
public class TestLambda02 {
public static void main(String[] args) {
ILove love = null;
love=(a,b,name)->{
System.out.println("灰太狼大概有-->"+a+"岁了");
System.out.println("喜羊羊大概有-->"+b+"岁了");
System.out.println("他的名字是-->"+name);
};
love.love(234,63,"智羊羊");
}
}
interface ILove{
void love(int a,int b,String name);
}
//测试线程停止
//线程最好正常停止--->利用次数,不建议死循环
//建议使用标志位--->设置一个标识位
//不要使用stop或者destroy等过时或者JDK不建议使用的方法
public class TestStop implements Runnable{
//设置一个标志位
private boolean flag=true;
@Override
public void run() {
int i=0;
while (flag){
System.out.println("线程开始运行----->"+(i++));
}
}
//设置一个公开的方法停止线程,转换标志位
public void stop(){
this.flag=false;
}
public static void main(String[] args) {
TestStop testStop=new TestStop();
new Thread(testStop).start();
for (int i = 0; i < 1000; i++) {
System.out.println("main"+i);
if (i==900){
testStop.stop();//调用stop方法转换标志位,停止线程!
System.out.println("线程停止!!!");
}
}
}
}
//模拟网络延时:放大问题的发生性
public class TestSleep implements Runnable{
private int ticketNum=10;
@Override
public void run() {
while (true){
if (ticketNum<=0){
break;
}
//模拟延时
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"-->拿到了第"+ticketNum--+"张票");
}
}
public static void main(String[] args) {
TestSleep runnableDemo02 = new TestSleep();
new Thread(runnableDemo02,"小李子").start();
new Thread(runnableDemo02,"小郭子").start();
new Thread(runnableDemo02,"盗版").start();
}
}
//实例模拟计时器
import java.text.SimpleDateFormat;
import java.util.Date;
public class TestSleep2 {
public static void main(String[] args) {
//打印当前时间
Date startTime=new Date(System.currentTimeMillis());//获得系统当前时间
while (true){
try {
Thread.sleep(1000);
System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(startTime));
startTime=new Date(System.currentTimeMillis());//更新系统当前时间
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
////模拟倒计时
// try {
// timeDown();
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
// }
// public static void timeDown() throws InterruptedException {
// int num=10;
// while (true){
// Thread.sleep(1000);
// System.out.println("倒计时-->"+(num--));
// if (num<=0){
// break;
// }
// }
// }
}
//礼让线程 不一定成功 看CPU心情
public class TestYield {
public static void main(String[] args) {
MyYield myYield = new MyYield();
new Thread(myYield,"A").start();
new Thread(myYield,"B").start();
}
}
class MyYield implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"线程开始执行!");
Thread.yield();//礼让
System.out.println(Thread.currentThread().getName()+"线程停止执行!");
}
}
//线程强制执行
public class TestJoin implements Runnable {
@Override
public void run() {
for (int i = 0; i < 500; i++) {
System.out.println("VIP线程先走!"+i);
}
}
public static void main(String[] args) throws InterruptedException {
//开启线程
TestJoin testJoin=new TestJoin();
Thread thread=new Thread(testJoin);
//主线程
for (int i = 0; i < 100; i++) {
if (i==50){
thread.start();
thread.join();//强制执行
}
System.out.println("main"+i);
}
}
}
//观察线程状态
public class TestState {
public static void main(String[] args) throws InterruptedException {
Thread thread=new Thread(()->{
for (int i = 0; i < 2; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程结束");
}
});
//观察线程状态
Thread.State state = thread.getState();
System.out.println(state);//NEW
//观察线程启动
thread.start();
state = thread.getState();//更新状态
System.out.println(state);//RUNNABLE
while (state!=Thread.State.TERMINATED){//只要线程不终止 就一直是输出状态
Thread.sleep(100);
state = thread.getState();//更新状态
System.out.println(state);
}
}
}
//线程优先级
public class TestPriority {
public static void main(String[] args) {
System.out.println(Thread.currentThread().getName()+"----->"+Thread.currentThread().getPriority());//主线程
MyPriority myPriority = new MyPriority();
Thread t1=new Thread(myPriority);
Thread t2=new Thread(myPriority);
Thread t3=new Thread(myPriority);
Thread t4=new Thread(myPriority);
Thread t5=new Thread(myPriority);
Thread t6=new Thread(myPriority);
//运行:先设置优先级,然后在启动
t1.start();
t2.setPriority(Thread.MIN_PRIORITY);//1
t2.start();
t3.setPriority(8);
t3.start();
t4.setPriority(Thread.MAX_PRIORITY);//10
t4.start();
t5.setPriority(4);
t5.start();
t6.setPriority(6);
t6.start();
}
}
class MyPriority implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"----->"+Thread.currentThread().getPriority());
}
}
//测试守护线程
public class TestDaemon {
public static void main(String[] args) {
God god = new God();
You you = new You();
Thread thread=new Thread(god);
thread.setDaemon(true);//默认值是false 表示用户线程 正常的线程都是用户线程
thread.start();//上帝 守护线程
new Thread(you).start();//You 用户线程启动
}
}
//上帝
class God implements Runnable{
//守护线程
@Override
public void run() {
while (true){
System.out.println("上帝一直都存在。");
}
}
}
//你
class You implements Runnable{
@Override
public void run() {
for (int i = 0; i < 36500; i++) {
System.out.println("你一直在活着。");
}
System.out.println("=========goodbye! world!=========");
}
}
同步方法和同步块:
public class UnSafeBank {
public static void main(String[] args) {
Account account = new Account(1000,"结婚基金");
Drawing youSister = new Drawing(account,50,"你姐姐");//你姐姐的
Drawing you = new Drawing(account,100,"you");//你的
youSister.start();
you.start();
}
}
//账户
class Account{
int money;//余额
String name;//卡号
public Account(int money, String name) {
this.money = money;
this.name = name;
}
}
//银行 模拟取款
class Drawing extends Thread{
Account account;//账户
int drawingMoney;//取得钱
int nowMoney;//现在有的钱
public Drawing(Account account, int drawingMoney,String name) {
super(name);
this.account = account;
this.drawingMoney = drawingMoney;
}
@Override
public void run() {
//锁的对象是变化的量----增删改
synchronized (account){
//判断卡内是否有钱
if (account.money-drawingMoney<0){
System.out.println(Thread.currentThread().getName()+"没钱了,取个毛线!");
return;
}
//时间延迟
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//取出钱
account.money=account.money-drawingMoney;
//现在还有的钱
nowMoney=nowMoney+drawingMoney;
System.out.println(account.name + "余额是:" + account.money);
//Thread.currentThread().getName()==>this.getName()
System.out.println(this.getName()+ "手里的钱是:" +nowMoney);
}
}
}
JUC测试:
import java.util.concurrent.CopyOnWriteArrayList;
//测试juc安全类型的集合 CopyOnWriteArrayList 安全的
public class TestJUC {
public static void main(String[] args) {
CopyOnWriteArrayList<String> list=new CopyOnWriteArrayList<String>();
for (int i = 0; i < 10000; i++) {
new Thread(()->{
list.add(Thread.currentThread().getName());
}).start();
}
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(list.size());
}
}
import java.util.concurrent.locks.ReentrantLock;
//测试Lock锁
public class TestLock {
public static void main(String[] args) {
MyLock myLock = new MyLock();
new Thread(myLock).start();
new Thread(myLock).start();
new Thread(myLock).start();
}
}
class MyLock implements Runnable{
//火车票
int ticketNum=10;
//定义lock锁
private final ReentrantLock reentrantLock=new ReentrantLock();
@Override
public void run() {
while (true){
//加锁
try {
reentrantLock.lock();
if (ticketNum>0){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(ticketNum--);
}else {
break;
}
} finally {
//解锁
reentrantLock.unlock();
}
}
}
}
//生产者消费者问题----通过设置缓冲区解决(管程法)
public class TestPC {
public static void main(String[] args) {
SynContainer synContainer = new SynContainer();
Producer producer = new Producer(synContainer);
Consumer consumer = new Consumer(synContainer);
producer.start();
consumer.start();
}
}
//生产者
class Producer extends Thread{
SynContainer container;
public Producer(SynContainer container) {
this.container = container;
}
//生产产品
@Override
public void run() {
for (int i = 0; i < 100; i++) {
container.push(new Product(i));
System.out.println("生产了---->"+i+"个产品。");
}
}
}
//消费者
class Consumer extends Thread{
SynContainer container;
public Consumer(SynContainer container) {
this.container = container;
}
//消费产品
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("消费了"+container.pop().id+"个产品*******");
}
}
}
//产品
class Product{
int id;//产品编号
public Product(int id) {
this.id = id;
}
}
//缓冲区 SynContainer
class SynContainer{
//设置产品的容器大小
Product[] products=new Product[10];
//设置计数器
int count=0;
//生产者生产产品
public synchronized void push(Product product){
//判断容器是否满了,如果满了,就需要等待消费者消费
if (count==products.length){
try {
this.wait(); //生产等待
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//如果容器不满,就需要生产者生产产品
products[count]=product;
count++;
//可以通知消费者消费了
this.notifyAll();
}
//消费者消费产品
public synchronized Product pop(){
//判断是否可以消费产品
if (count==0){
//消费者等待
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//如果可以消费
count--;
Product product=products[count];
//可以通知生产者进行生产了
this.notifyAll();
return product;
}
}
原文:https://www.cnblogs.com/javastudys/p/java_05.html