多线程
Thread类
多条执行路径,主线程和子线程并行交替执行
package xiancheng;
public class Demo01 extends Thread{
//创建线程方式一:继承Thread类,重写run方法,调用start开启线程
@Override
public void run() {
//run方法线程体
for (int i = 0; i < 20; i++) {
System.out.println("我在看代码");
}
}
public static void main(String[] args) {
//创建一个线程对象
Demo01 test = new Demo01();
//使用start方法调用
test.start();
//main主线程
for (int i = 0; i < 20; i++) {
System.out.println("我在学习多线程");
}
}
}
实现Runnable接口
package xiancheng;
public class Demo02 implements Runnable{
//创建线程方式2:实现Runnable接口,重写run方法,执行线程需要丢入runnable接口实现类,调用start方法
@Override
public void run() {
//run方法线程体
for (int i = 0; i < 20; i++) {
System.out.println("我在看代码");
}
}
public static void main(String[] args) {
//创建runnable接口实现类对象
Demo02 test = new Demo02();
//创建线程对象,通过线程对象来开启我们的线程,代理
new Thread(test).start();
//main主线程
for (int i = 0; i < 20; i++) {
System.out.println("我在学习多线程");
}
}
}
继承thread类:子类继承thread类具备多线程能力;
启动线程(子类独享,start());
不建议使用:避免oop单继承局限性
实现Runnable接口:实现接口Runnable具备多线程能力;
启动线程:传入目标对象+thread对象.start();
推荐使用:避免单继承局限性,灵活方便,方便同一个对象被多个线程使用
静态代理
package xiancheng;
public class Demo04 {
//静态代理模式总结:真实对象和代理对象都要实现同一个接口
//代理对象要代理真实角色
//好处
//代理对象可以做很多真实对象做不了的事情
//真实对象可以专注于做自己的事情
public static void main(String[] args) {
You you = new You();//主体:你要结婚
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("结婚之前,布置现场");
}
}
Lamda表达式
避免匿名内部类定义过多
其实质是属于函数式编程的概念
函数式接口(Functional interface
函数式接口的定义:如何接口,如果只是包含唯一一个抽象方法,那么他就是一个函数式。
对于函数式接口,我们可以通过lambda表达式来创建改接口的对象
package xiancheng;
public class Testlambda2 {
public static void main(String[] args) {
ILove love=(int a)->{
System.out.println("我喜欢你>>"+a);
};
//简化1:参数类型
love=(a)->{
System.out.println("我喜欢你>>"+a);
};
//简化2:简化括号
love=a->{
System.out.println("我喜欢你>>"+a);
};
//简化3:去掉花括号
love=a-> System.out.println("我喜欢你>>"+a);
//总结
//lambda表达式只能有一行代码的情况下才能简化成为一行,如果有多行,那么就用代码块包裹(也就是花括号
//前提是函数式接口(接口内只有一个方法
//多个参数也可以去掉参数类型,要去掉就都去掉(统一
love.love(520 );
}
}
interface ILove{
void love(int a);
}
package xiancheng;
public class Testlambda1 {
//推到lambda表达式
//3.使用静态内部类继续简化代码
static class Like2 implements ILike{
@Override
public void lambda() {
System.out.println("我喜欢lambda2");
}
}
public static void main(String[] args) {
ILike like=new Like();
like.lambda();
like=new Like2();
like.lambda();
//4.局部内部类
class Like3 implements ILike{
@Override
public void lambda() {
System.out.println("我喜欢lambda3");
}
}
like=new Like3();
like.lambda();
//5.匿名内部类
like=new ILike() {
@Override
public void lambda() {
System.out.println("我喜欢lambda4");
}
};
like.lambda();
//使用lambda来简化
like=()->{
System.out.println("我喜欢lambda5");
};
like.lambda();
}
}
//1.定义一个函数式接口
interface ILike{
void lambda();
}
//2.实现类
class Like implements ILike{
@Override
public void lambda() {
System.out.println("我喜欢lambda");
}
}
线程停止
不推荐jdk提供的方法
推荐线程自己停止下来
建议使用一个标志位进行终止变量,当flag=flase时候则终止线程
网络延时
模拟网络延时:放大问题的发生性
每个对象都有一把锁,sleep不会释放锁
package xiancheng;
public class Demo06 {
//模拟倒计时
public static void main(String[] args) {
try {
tenDown();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void tenDown() throws InterruptedException{
int num=10;
while (true){
Thread.sleep(1000);
System.out.println(num--);
if (num<=0){
break;
}
}
}
}
礼让线程
礼让线程,让当前正在执行的线程暂停,但是不阻塞
将线程从运行状态转为就绪状态
让cpu重新调度,礼让不一定成功,看cpu心情
package xiancheng;
public class Demo07 {
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()+"线程停止执行");
}
}
join
join可以合并线程,待此线程执行完成后,在执行其他线程,其他线程阻塞
可以想象成插队
package xiancheng;
public class TestJoin implements Runnable{
//在插队之前;两个线程并行,当i打到200的时候,使用join方法,就会让主线程阻塞,知道run跑完结束后,才会继续跑主线程
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("线程VIP来咯"+i);
}
}
//启动我们的线程
public static void main(String[] args) throws InterruptedException {
TestJoin testJoin = new TestJoin();
Thread thread = new Thread(testJoin);
thread.start();
//主线程
for (int i = 0; i < 500; i++) {
if (i==200){
thread.join();//插队
}
System.out.println("main"+i);
}
}
}
线程优先级
java提供一个线程调度器来监控程序中启动后进入就绪状态的所有线程,线程调度按照优先级决定应该调度那个线程来执行。
线程的优先级用数字来表示,范围从1-10,默认为5
优先级低只是意味着获得调度的概率低,并不是优先级低就不会被调用了,这还得看cpu 的调度
package xiancheng;
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);
//先设置优先级,在进行启动
t1.start();
t2.setPriority(1);
t2.start();
t3.setPriority(4);
t3.start();
t4.setPriority(Thread.MAX_PRIORITY);//MAX_PRIORITY最大优先级:10
t4.start();
}
}
class MyPriority implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"--->"+Thread.currentThread().getPriority());
}
}
守护(daemon)线程
线程分为用户线程和守护线程
虚拟机必须确保用户线程执行完毕
虚拟机不用等待守护线程执行完毕
package xiancheng;
public class TestDaemon {
//测试守护线程
public static void main(String[] args) {
God god = new God();
WXY you = new WXY();
Thread thread = new Thread(god);
thread.setDaemon(true);//默认是false表示是用户线程,正常线程都是用户线程
thread.start();//上帝守护线程启动
new Thread(you).start();//王新宇线程启动
//当王新宇(用户线程)结束的时候,虚拟机停止,不需要在乎守护线程时候结束
}
}
//god
class God implements Runnable{
@Override
public void run() {
while (true){
System.out.println("上帝保佑着你");
}
}
}
//王新宇
class WXY implements Runnable{
@Override
public void run() {
for (int i = 0; i < 360000; i++) {
System.out.println("开心的活着");
}
System.out.println("gg");
}
}
线程同步(代码没有理解,所以没打代码
同步块:synchronized(obj){}
obj称为同步监视器。
同步监视器的执行过程:第一个线程访问,锁定同步监视器,执行其中代码
第二个线程访问,发现同步监视器被锁定,无法访问,第三个线程访问完毕,解锁同步监视器
第二个线程访问,发现同步监视器没有锁,然后锁定并访问
JUC表达式(可恶,好难
package xiancheng;
import java.util.concurrent.CopyOnWriteArrayList;
public class TestJUC {
//测试juc安全类型的集合
public static void main(String[] args) {
CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>();
for (int i = 0; i < 1000; i++) {
new Thread(()->{
list.add(Thread.currentThread().getName());
}).start();
}
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(list.size());
}
}
死锁
synchronized与lock的对比
- lock是显示所(需要手动开启和关闭锁,别忘记关闭所)synchronized是隐式锁,出了作用域自动释放
- lock只有代码块锁,synchronized有代码块锁和方法锁
- 使用lock锁,jvm将花费少的时间来调度线程,性能更好,并且具有更好的扩展性,(提供更多的子类
- 使用优先顺序:lock>同步代码块>同步方法
package xiancheng;
import java.util.concurrent.locks.ReentrantLock;
public class Deadlock {
//测试lock锁
public static void main(String[] args) {
TestLock testLock = new TestLock();
new Thread(testLock).start();
new Thread(testLock).start();
new Thread(testLock).start();
}
}
class TestLock implements Runnable{
int ticketNum=10;
//定义lock锁
private final ReentrantLock lock=new ReentrantLock();
@Override
public void run() {
while (true){
try {
lock.lock();//加锁
if (ticketNum>0){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(ticketNum--);
}else {
break;
}
}finally {
lock.unlock();//解锁
}
}
}
}
线程协作
线程池
jdk提供了线程池相关api:executorservice和executors
executorservice:真正的线程池接口,常见的子类Threadpoolexecutor
executors:工具类,线程池的工厂类,用于创建并返回不同类型的线程池
package xiancheng;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Demo08 {
//测试线程池
public static void main(String[] args) {
//创建服务,创建线程池
ExecutorService service= Executors.newFixedThreadPool(10);
service.execute(new MyThread());
service.execute(new MyThread());
service.execute(new MyThread());
service.execute(new MyThread());
//关闭连接
service.shutdown();
}
}
class MyThread implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
}
标签:Thread,void,理解,线程,println,new,public,到位
From: https://www.cnblogs.com/-lhrbk/p/17259636.html