多任务:一个接一个做,不同时
多线程:同时
交替执行,每次执行结果不一样,由cpu调度
package com.liu.www;
//1.继承Thread类 2.重写run方法 3.写main主线程 4.new 对象调用它的start方法
public class TestThread extends Thread {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("摸摸大 "+i);
}
}
public static void main(String[] args) {
//主线程
TestThread testThread = new TestThread();
testThread.start();//start相当于开辟了一条新的线程
for (int i = 0; i < 5000; i++) {
System.out.println("0000000"+i);
}
}
}
图片下载练习:
package com.liu.www;
import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.IOException;
import java.net.URL;
public class TestThread2 extends Thread {
private String url;
private String file;
public TestThread2(String url, String file) {
this.url = url;
this.file = file;
}
//下载图片线程的执行体
@Override
public void run() {
ImgDownload imgDownload = new ImgDownload();
imgDownload.download(url,file);
System.out.println("下载了文件,文件名是"+file);
}
public static void main(String[] args) {
TestThread2 t1= new TestThread2("https://pics1.baidu.com/feed/03087bf40ad162d9cbb3cc2d87b712eb8a13cd16?token=ba35ec7e6b5f5aeadb4bea873a4e4b27&s=AD717B8444D13DF50839C8140300B091&f=jpeg","1.jpg");
TestThread2 t2= new TestThread2("https://pics1.baidu.com/feed/1c950a7b02087bf47fe23ffe64bbec2b11dfcf0f?token=39be00f2b209980a21dbaff3c28e1961&s=FEA00DC042E09CE61C38458E0300E002&f=jpeg","2.jpg");
TestThread2 t3= new TestThread2("https://pics1.baidu.com/feed/279759ee3d6d55fb4833a93bfb4af44d21a4dda3?token=7d10a89c5b4a66f2409156fc61feaf13&s=F21F30C48661974F587271110300C0CA&f=jpeg","3.jpg");
t1.start();
t2.start();
t3.start();
}
}
//下载器类
class ImgDownload{
public void download(String url,String file ){
try {
FileUtils.copyURLToFile(new URL(url),new File(file));
} catch (IOException e) {
e.printStackTrace();
System.out.println("下载器出现错误");
}
}
}
2.实现Runnable
因为java单继承,推荐使用Runnable,多个线程去操作一个对象
package com.liu.www;
//1.继承Thread类 2.重写run方法 3.写main主线程 4.new 线程对象调用它的start方法
public class TestThread3 implements Runnable {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("摸摸大 " + i);
}
}
public static void main(String[] args) {
//主线程
TestThread3 testThread = new TestThread3();
//主要就是多这一步,new一个thread,把testThread丢进去
Thread thread = new Thread(testThread);
thread.start();
for (int i = 0; i < 5000; i++) {
System.out.println("0000000" + i);
}
}
}
package com.liu.www;
//并发问题:
//多个线程同时操作一个对象:火车票的例子
public class TestThread4 implements Runnable {
//票数
private int ticketNums=10;
@Override
public void run() {
while (true){
if (ticketNums<=0){
break;
}else {
System.out.println(Thread.currentThread().getName()+ "拿到了第"+ticketNums--+"票");
}
}
}
public static void main(String[] args) {
TestThread4 testThread4 = new TestThread4();
new Thread(testThread4,"周欢").start();
new Thread(testThread4,"刘可").start();
new Thread(testThread4,"张钢").start();
}
}
3.lamda表达式
函数式接口:只包含一个抽象方法
package com.liu.www;
public class Race {
//3.定义静态内部类(优化1,类在外面很麻烦)
static class baby2 implements interest{
@Override
public void inter() {
System.out.println("你想要我对lamda感兴趣嘛----two");
}
}
public static void main(String[] args) {
//定义一个接口的实现类
interest baby = new baby();
baby.inter();
baby = new baby2();
baby.inter();
//4.定义局部内部类(优化2,类放在方法里面)
class baby3 implements interest{
@Override
public void inter() {
System.out.println("你想要我对lamda感兴趣嘛----three");
}
}
baby = new baby3();
baby.inter();
//5.匿名内部类(优化3,没有类名,借助父类或者接口)
baby=new interest() {
@Override
public void inter() {
System.out.println("你想要我对lamda感兴趣嘛----four");
}
};
baby.inter();
//6.lamba简化
baby=()->{
System.out.println("你想要我对lamda感兴趣嘛----five");
};
baby.inter();
}
}
//1.首先定义函数式接口
interface interest{
void inter();
}
//2.定义一个类去实现这个接口
class baby implements interest{
@Override
public void inter() {
System.out.println("你想要我对lamda感兴趣嘛");
}
}
输出结果:
你想要我对lamda感兴趣嘛
你想要我对lamda感兴趣嘛----two
你想要我对lamda感兴趣嘛----three
你想要我对lamda感兴趣嘛----four
你想要我对lamda感兴趣嘛----five
这个例子是无参数的,有参数的在()->的()里面写参数即可,参数的类型可以省略
4.线程五大状态
- 停止线程
-
建议线程通过设置次数自动停止,不建议死循环
-
建议使用标志位
-
jdk官方的不推荐的stop(),destroy()不使用
package com.liu.www;
-
public class Demo_02 implements Runnable{
//1.设置一个标志位
private boolean flag=true;
@Override
public void run() {
int i=0;
while (flag){
System.out.println("------------0000000000"+i++);
}
}
//2.设置一个公开的方法停止线程,转换标志位
public void stop(){
this.flag=false;
}
public static void main(String[] args) {
Demo_02 demo_02 = new Demo_02();
new Thread(demo_02).start();
for (int i = 0; i < 10000; i++) {
System.out.println("主线程正在执行"+i);
if (i==9000){
//调用stop方法切换标志位,让线程停止
demo_02.stop();
System.out.println("线程停止了");
}
}
}
}
-
线程休眠 sleep() 放大问题的发生性
package com.liu.www; import java.text.SimpleDateFormat; import java.util.Date; public class Demo_03 { public static void main(String[] args) throws InterruptedException { // tendown(); //打印系统当前时间 Date date = new Date(System.currentTimeMillis()); while (true){ Thread.sleep(1000); System.out.println(new SimpleDateFormat("yyyy-MM-dd-HH:mm:ss").format(date)); date = new Date(System.currentTimeMillis()); } } //模拟倒计时 public static void tendown() throws InterruptedException { for (int i = 10; i >= 0; i--) { Thread.sleep(1000); System.out.println(i); } } } -
线程礼让 yield
package com.liu.www;
public class TestYield {
public static void main(String[] args) {
myyield my = new myyield();
new Thread(my,"a").start();
new Thread(my,"b").start();
}
}
class myyield implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"线程开始执行");
Thread.yield();
System.out.println(Thread.currentThread().getName()+"线程停止执行");
}
输出结果:
a线程开始执行
b线程开始执行
a线程停止执行
b线程停止执行
或者b
a线程开始执行
a线程开始执行
b线程停止执行
b线程停止执行
- join() 插队
用户线程:main()
7.线程同步多个线程操作同一个资源
排队解决:就是队列
锁:景区厕所的门锁
线程同步:就是队列+锁 保证线程的安全性
synchronized:同步的
[[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xOi6D2Xo-1639320833341)(C:Users密西西比的守望AppDataRoamingTyporatypora-user-imagesimage-20210107230030300.png)]
线程不安全:不安全的主要原因在于线程都有各自的内存,互不影响
- 出现负数
- list数据覆盖
第一种方法:synchronized 直接加给方法的
第二种方法:synchronized(obj){ 这个obj是变化的量 增删改
这里写方法
}
JUC并发编程
死锁:
多个线程互相抱着对方需要的资源,然后形成僵持
lock锁:
jdk5开始出现使用 reentantlock:可重复锁
8.线程协作生产者消费者问题:
管程法
信号灯法
9.线程池package com.liu.www;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import static java.util.concurrent.Executors.newFixedThreadPool;
//测试线程池
public class TestPool {
public static void main(String[] args) {
//1.创建服务,创建线程池 newFixedThreadPool 参数为线程池的大小
ExecutorService Service = newFixedThreadPool(10);
Service.execute(new MyThread());
Service.execute(new MyThread());
Service.execute(new MyThread());
Service.execute(new MyThread());
//2.关闭连接
Service.shutdown();
}
}
class MyThread implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
}
输出结果:
pool-1-thread-1
pool-1-thread-2
pool-1-thread-3
pool-1-thread-4
readPool 参数为线程池的大小
ExecutorService Service = newFixedThreadPool(10);
Service.execute(new MyThread());
Service.execute(new MyThread());
Service.execute(new MyThread());
Service.execute(new MyThread());
//2.关闭连接
Service.shutdown();
}
}
class MyThread implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
}
输出结果:
pool-1-thread-1
pool-1-thread-2
pool-1-thread-3
pool-1-thread-4



