JAVA线程与并发

JAVA线程与并发(完善中)

1.1 线程创建

1.1.1 Thread class集成Thread类 实现run方法

自定义线程类继承Thread类

public class TestThread1 extends Thread {
    @Override
    public void run() {
        for(int i = 0;i < 200;i++){
            System.out.println("输出+++++++" + i);
        }
    }
    public static void main(String[] args) {
        TestThread1 testThread1 = new TestThread1();

        testThread1.start();
        for(int i = 0;i < 200;i++){
            System.out.println("输出" + i);
        }
    }
}

1.1.2 Runnable接口实现Runable接口 实现run方法

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();
        //简写  -- 可以使得 多个testThread3 对象 被多个线程同时使用
        new Thread(testThread3).start();

        for(int i = 0;i < 200;i++){
            System.out.println("输出" + i);
        }
    }
}

1.1.3 实现Callable接口

创建执行服务

ExecutorService service = Executors.newFixedThreadPool(3);

顶级接口Executor(执行线程的工具) ExecutorService(真正的线程池接口)

这里的创建的线程池的不同

  • CachedThreadPool 创建带有缓存的线程池,没有核心线程,非核心线程数量不限制;调用execute将重用一起构造的线程(如果线程可用),如果没有现有线程 则重新创建。终止并重缓存中移除60秒未被使用的线程

  • ScheduledThreadPool 创建带有核心线程的线程池,拥有非核心线程,非核心线程数量不限制

  • SingleThreadPool 单一线程池 只返回一个线程,可以在发生异常或死亡时重新生成一个新的线程代替继续执行

  • FixedThreadPool 创建 可重用的固定线程数量的线程池,以共享无界队列的方式运行这些线程 ; 只有核心线程 的线程池

//缓存型池子,先查看池中有没有以前建立的线程,如果有,就 reuse.如果没有,就建一个新的线程加入池中,在此之中的线程 超过TIMEOUT不活动,会自动被终止。
ExecutorService service = Executors.newCachedThreadPool() 
//任意时间点,最多只能有固定数目的活动线程存在 此时如果有新的线程要建立,只能放在另外的队列中等待,直到当前的线程中某个线程终止直接被移出池子
ExecutorService service = Executors.newFixedThreadPool(int)  
//调度型线程池 这个池子里的线程可以按schedule依次delay执行,或周期执行
ExecutorService service = Executors.newScheduledThreadPool(int)
//单例线程,任意时间池中只能有一个线程
ExecutorService service = Executors.SingleThreadExecutor()
import org.apache.commons.io.FileUtils;

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() throws Exception {
        WDownloader webDownloader = new WDownloader();
        webDownloader.downloader(url,name);
        System.out.println("下载文件名:" + name);
        return true;
    }

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        TestCallable t1 = new TestCallable("https://tpc.googlesyndication.com/simgad/9451486580539342396/downsize_200k_v1?w=600&h=314","1");
        TestCallable t2 = new TestCallable("https://tpc.googlesyndication.com/simgad/9451486580539342396/downsize_200k_v1?w=600&h=314","2");
        TestCallable t3 = new TestCallable("https://tpc.googlesyndication.com/simgad/9451486580539342396/downsize_200k_v1?w=600&h=314","3");

        //创建执行服务
        ExecutorService service = Executors.newFixedThreadPool(3);

        //提交执行任务
        Future<Boolean> future1 = service.submit(t1);
        Future<Boolean> future2 = service.submit(t2);
        Future<Boolean> future3 = service.submit(t3);

        //获取结果
        boolean res1 = future1.get();
        boolean res2 = future2.get();
        boolean res3 = future3.get();

        //关闭服务
        service.shutdown();

        System.out.println(res1);
        System.out.println(res2);
        System.out.println(res3);
    }
}

class WDownloader{
    public void downloader(String url,String name){
        try {
            FileUtils.copyURLToFile(new URL(url), new File(name));
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("IO Exception !!! ");
        }
    }
}

1.2 线程同步的方法

1.2.1 synchronized 同步锁

Java中是为 非公平锁 JVM自解锁

可以 锁整个方法、或者 锁代码块

1.2.2 ReEntrantLock(重入锁)

通过 lock 和 unlock 来进行加锁 与解锁操作 必须要需手动解锁 默认的lock是为非公平锁 可以设置为公平锁

1.2.3 Semaphore 信号量同步

信号无需由同一个线程来获取和释放,因此信号可用于异步事件通知,

信号包含状态,因此可以异步方式使用,而不用象条件变量那样要求获取互斥锁。

信号的 效率 不如 互斥锁 高

1.2.3.1PV原语

PV原语通过操作信号量来处理进程间的同步与互斥的问题。其核心就是一段不可分割不可中断的程序

P原语操作的动作是: (1)sem减1; (2)若sem减1后仍大于或等于零,则进程继续执行; (3)若sem减1后小于零,则该进程被阻塞后进入与该信号相对应的队列中,然后转进程调度。

V原语操作的动作是: (1)sem加1; (2)若相加结果大于零,则进程继续执行; (3)若相加结果小于或等于零,则从该信号的等待队列中唤醒一等待进程,然后再返回原进程继续执行或转进程调度。

PV操作对于每一个进程来说,都只能进行一次,而且必须成对使用。在PV原语执行期间不允许有中断的发生。

1.2.4 AtomicInteger 类

是一个提供原子操作的Integer 的类,性能会比 ReEntrantLock 好几倍

AtomicBoolean、 AtomicLong、 AtomicReference等;

AtomicReference:可以使用AtomicReference将一个对象的所有操作转化成原子操

1.2.5 可重入锁(递归锁)

外层函数获取到锁后 内层函数仍有获得该锁的代码 但不受影响

Java环境下 ReentrantLock 和 Synchronize 都是可重入锁

1.3 静态代理模式

/** 静态代理模式总结
 * 
 * 真是对象和代理对象都是要实现同一个接口
 * 代理对象要代理真实角色
 *
 * 好处:
 *      代理对象可做很多真实对象无法做到的事
 *      真实对象专注于自己的业务
 */
public class StacticProxy {
    public static void main(String[] args) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("111");
            }
        }).start();
        
        new Thread( () -> System.out.println("111")).start();

        WeddingCompany weddingCompany = new WeddingCompany(new You());
        weddingCompany.HappyMarry();
        
        new WeddingCompany(new You()).HappyMarry();
    }
}

interface Marry{
    void HappyMarry();
}

class You implements Marry{
    @Override
    public void HappyMarry() {
        System.out.println("You Happy Marry!");
    }
}

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("After");
    }

    private void before() {
        System.out.println("Before");
    }
}

1.4 Lambda表达式

1.4.1 Lambda好处

  • 避免匿名内部类定义过多
  • 去掉了没有意义的代码 只留下核心的逻辑

1.4.2 理解函数式接口

  • Functional Interface(函数式接口)是学习Lambda的关键

  • 函数式接口的定义

    • 任何接口 如果只包含唯一一个抽象方法,那么它就是一个函数式接口。

      public interface Runnable{
          public abstract void run();
      }
      
    • 对于函数式接口,我们可以通过Lambda表达式来创建该接口的对象

1.5 sleep()、wait()

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值