创建线程的方法一: 继承Thread类
继承Thread类,重写run()方法,调用start开启线程
//创建线程方式一:继承Thread类,重写run()方法,调用start开启线程
public class TestThread1 extends Thread{
@Override
public void run() {
//run方法线程体
for (int i = 0; i < 20; i++) {
System.out.println("我在看代码"+i);
}
}
public static void main(String[] args) {
//创建线程对象,调用start方法开启线程
TestThread1 th = new TestThread1();
th.start();
//主线程
for (int i = 0; i < 200; i++) {
System.out.println("我在学习多线程"+i);
}
}
}
线程开启不一定立即执行,由cpu调度执行
创建线程的方法二:实现Runnable接口
实现Runnable接口
重写run()方法
执行线程需要丢人runnable的实现类
//创建线程方式2:实现runnable接口,重写run()方法,执行线程需要丢人runnable接口的实现类,调用start
public class TestThread3 implements Runnable {
@Override
public void run() {
for (int i = 0; i < 200; i++) {
System.out.println("我在看代码"+i);
}
}
public static void main(String[] args) {
TestThread3 testThread3 = new TestThread3();
Thread thread = new Thread(testThread3);
thread.start();
for (int i = 0; i < 1000; i++) {
System.out.println("我在学习多线程"+i);
}
}
}
继承Thread类不建议使用,避免oop单继承的局限性
推荐使用runnable,方便同一个对象被多个线程使用
创建线程的方法三:实现callable接口
package thread.demo02;
import org.apache.commons.io.FileUtils;
import thread.demo01.TestThread2;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.concurrent.*;
//线程创建方式三:实现callable接口
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 {
// TestThread2 t1 = new TestThread2("https://blog.kuangstudy.com/usr/thems/handsome/usr/img/sj/1.jpg","1.jpg");
// TestThread2 t2 = new TestThread2("https://blog.kuangstudy.com/usr/thems/handsome/usr/img/sj/2.jpg","2.jpg");
// TestThread2 t3 = new TestThread2("https://blog.kuangstudy.com/usr/thems/handsome/usr/img/sj/3.jpg","3.jpg");
TestCallable t1 = new TestCallable("https://img2020.cnblogs.com/blog/2064460/202006/2064460-20200625190604419-1455422592.png","1.jpg");
TestCallable t2 = new TestCallable("https://img2020.cnblogs.com/blog/2064460/202006/2064460-20200625190911817-83431247.png","2.jpg");
TestCallable t3 = new TestCallable("https://img2020.cnblogs.com/blog/2064460/202006/2064460-20200625191026128-506397148.png","3.jpg");
//创建执行服务
ExecutorService ser = Executors.newFixedThreadPool(3);
//提交执行
Future<Boolean> r1=ser.submit(t1);
Future<Boolean> r2=ser.submit(t2);
Future<Boolean> r3=ser.submit(t3);
//获取结果
boolean rs1= r1.get();
boolean rs2= r2.get();
boolean rs3= r3.get();
//关闭服务
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();
}
}
}
callable的好处
1.定义返回值
2.可抛出异常
静态代理
静态代理模式
真实对象和代理对象都要实现同一个接口
代理对象要代理真实角色
好处:代理对象可以做真实对象做不了的事,真实对象专注做自己的事
package thread.demo03;
//静态代理模式
//真实对象和代理对象都要实现同一个接口
//代理对象要代理真实角色
//好处:代理对象可以做真实对象做不了的事,真实对象专注做自己的事
public class StaticProxy {
public static void main(String[] args) {
You you = new You();
new Thread(()-> System.out.println("我爱你")).start();
new WeddingCompany(new You()).HappyMarry();
// WeddingCompany weddingCompany = new WeddingCompany(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 after() {
System.out.println("结婚后收尾款");
}
private void before() {
System.out.println("结婚前布置现场");
}
}
线程状态
- 创建状态
- 就绪状态
- 运行状态
- 阻塞状态
- 死亡状态
线程停止
设置标志位
package thread.state;
//测试stop
//1.建议线程正常停止-->利用次数,不建议死循环
//2.建议使用标志位
//3.不要使用stop等过时方法
public class TestStop implements Runnable {
//1.设置标志位
private boolean flag = true;
@Override
public void run() {
int i=0;
while (flag){
System.out.println("线程运行中"+i++);
}
}
//2。设置公开的方法停止线程,转换标志位
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(i);
if(i==900){
testStop.stop();
System.out.println("线程停止了");
}
}
}
}
线程休眠
每个对象都有一个锁,sleep不会释放锁
package thread.state;
//1.模拟网络延时,放大问题的发生性
public class TestSleep implements Runnable{
//票数
private int ticketNums = 10;
@Override
public void run() {
while (true){
if(ticketNums<=0){
break;
}
//模拟延时
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"拿到了"+ticketNums--+"票");
}
}
public static void main(String[] args) {
TestSleep testThread4 = new TestSleep();
new Thread(testThread4,"小明").start();
new Thread(testThread4,"老师").start();
new Thread(testThread4,"黄牛").start();
}
}
线程礼让
yield
可能成功,可能失败
线程强制执行
join
线程优先级
线程优先级低只是调度的概率低,具体还是看cpu调度
thread.priority
package thread.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(1);
t2.start();
t3.setPriority(4);
t3.start();
t4.setPriority(10);
t4.start();
// t5.setPriority(-1);
// t5.start();
// t6.setPriority(11);
// t6.start();
}
}
class MyPriority implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"-->"+Thread.currentThread().getPriority());
}
}
守护线程
daemon
thread.setDaemon(true);
线程同步
- 队列和锁
- 保证线程同步安全性
- synchronized
死锁
- 互斥条件:一个资源一次只能被一个线程使用
- 请求与保持:一个进程因请求资源而阻塞,对已经获得的资源保持不放
- 不剥夺:进程已经获得的资源,在未使用完之前不能强行剥夺
- 循环等待:若干进程之间形成的头尾相接的循环等待资源关系
lock锁
package thread.lock;
import java.util.concurrent.locks.ReentrantLock;
//测试lock锁
public class TestLock {
public static void main(String[] args) {
TestLock2 testLock2 = new TestLock2();
new Thread(testLock2).start();
new Thread(testLock2).start();
new Thread(testLock2).start();
}
}
class TestLock2 implements Runnable{
int ticketNums = 1000;
//定义lock锁
private ReentrantLock reentrantLock = new ReentrantLock();
@Override
public void run() {
while(true){
try {
// try {
// Thread.sleep(1000);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
reentrantLock.lock();
if(ticketNums>0){
System.out.println(Thread.currentThread().getName()+"-》"+ticketNums--);
}
else
{
break;
}
}finally {
reentrantLock.unlock();
}
}
}
}
线程协作–生产者消费者模式
管程法及信号灯法
线程池
package thread.gaoji;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class TestPool {
public static void main(String[] args) {
//1.创建服务,创建线程池
ExecutorService service = Executors.newFixedThreadPool(10);
//2.执行
service.execute(new MyThread());
service.execute(new MyThread());
service.execute(new MyThread());
service.execute(new MyThread());
//3.关闭连接
service.shutdown();
}
}
class MyThread implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+i);
}
}