一课掌握Java并发编程精髓(完结13章)

198 阅读5分钟

资料地址1:pan.baidu.com/s/1bPKpzdB6… 提取码: ik4v 资料地址2:share.weiyun.com/VtbcAU8C 密码:gmqctf

一课掌握Java并发编程精髓,分13章讲解,又名:Java并发编程从入门到进阶 多场景实战。

并发编程是优秀工程师的标准之一,但知识庞杂,复杂性高,常常让人望而却步。如果没有掌握背后的核心原理,你开发的代码可能会成为难以调试和优化的头疼问题。因此本文将通过上百个案例场景驱动教学+动画直观演示,帮助入门级程序员深入、直观地理解并发编程核心概念和底层原理,构建一个扎实的知识框架;同时也帮助有一定工作经验的程序员提升并发技术实战能力,强化复杂并发问题解决能力,攻克绝大多数面试疑难问题,助力大家在实际工作和面试中都能尽早脱颖而出。

文章内容包含:深度剖析线程安全性问题与底层原理、 Java中的7大常用锁实战、并发容器的线程安全性与实战、线程池原理剖析与实战、线程间的协作原理场景剖析、高性能队列 Disruptor原理剖析、限流器RateLimit原理剖析、并发深入底层--Java内存模型(JMM)入门、并发性能测试、具体问题排查等等。

首先,我们需要理解并发编程的重要性。在单线程环境中,我们不需要考虑线程间的同步问题,因为只有一个线程在操作数据,不存在竞态条件。然而,当我们引入多线程时,同一时间可能有多个线程同时操作同一份数据,如果没有合适的同步措施,可能会导致数据的不一致性。而数据的不一致性在某些场景下,可能导致严重的问题,例如:重复的银行交易、脏读等。

java怎么实现并发,接下来我将以代码实战给大家讲解: 我们需要借助于第三方jar包jedis来操作 首先在idea中创建maven项目db_redis 在pom.xml文件中添加jedis依赖 package com.imooc.redis;

import redis.clients.jedis.Jedis;

/**

  • 单连接方式操作redis

  • Created by xuwei / public class RedisSingle { /*

    • 注意:此代码能够正常执行的前提是

    • 1:redis所在服务器的防火墙需要关闭

    • 2:redis.conf中的bind参数需要指定192.168.182.103

    • @param args */ public static void main(String[] args) { //获取jedis连接 Jedis jedis = new Jedis("192.168.182.103",6379); //向redis中添加数据,key=imooc,value=hello bigdata! jedis.set("imooc","hello bigdata!"); //从redis中查询key=imooc的value的值 String value = jedis.get("imooc");

      System.out.println(value);

      //关闭jedis连接 jedis.close();

    } } 接下来使用连接池的方式操作redis 代码如下: package com.imooc.redis;

import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; import redis.clients.jedis.JedisPoolConfig;

/**

  • 连接池的方式操作redis

  • Created by xuwei */ public class RedisPool { public static void main(String[] args) { //创建连接池配置对象 JedisPoolConfig poolConfig = new JedisPoolConfig(); //连接池中最大空闲连接数 poolConfig.setMaxIdle(10); //连接池中创建的最大连接数 poolConfig.setMaxTotal(100); //创建连接的超时时间 poolConfig.setMaxWaitMillis(2000); //表示从连接池中获取连接的时候会先测试一下连接是否可用,这样可以保证取出的连接都是可用的 poolConfig.setTestOnBorrow(true);

     //获取jedis连接池
     JedisPool jedisPool = new JedisPool(poolConfig, "192.168.182.103", 6379);
    
     //从jedis连接池中取出一个连接
     Jedis jedis = jedisPool.getResource();
     String value = jedis.get("imooc");
     System.out.println(value);
     //注意:此处的close方法有两层含义
     //1:如果jedis是直接创建的单连接,此时表示直接关闭这个连接
     //2:如果jedis是从连接池中获取的连接,此时会把这个连接返回给连接池
     jedis.close();
     
     //关闭jedis连接池
     jedisPool.close();
    

    } } 基于redis连接池的方式提取RedisUtils工具类 package com.imooc.redis;

import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; import redis.clients.jedis.JedisPoolConfig;

/**

  • 基于redis连接池提取redis工具类

  • Created by xuwei */ public class RedisUtils { //私有化构造函数,禁止new private RedisUtils(){}

    private static JedisPool jedisPool = null;

    //获取连接 public static synchronized Jedis getJedis(){ if(jedisPool==null){ JedisPoolConfig poolConfig = new JedisPoolConfig(); poolConfig.setMaxIdle(10); poolConfig.setMaxTotal(100); poolConfig.setMaxWaitMillis(2000); poolConfig.setTestOnBorrow(true); jedisPool = new JedisPool(poolConfig, "192.168.182.103", 6379); } return jedisPool.getResource(); }

    //向连接池返回连接 public static void returnResource(Jedis jedis){ jedis.close(); }

} 其中有一些特殊用法:int = Int32 float = Float32,大家看到这些写法能认出来就行了。 在SQL编辑器中执行并且验证。 [root@bigdata04 ~]# timedatectl Local time: Wed 2028-05-17 16:59:27 CST Universal time: Wed 2028-05-17 08:59:27 UTC RTC time: Wed 2028-05-17 08:59:27 Time zone: Asia/Shanghai (CST, +0800) NTP enabled: n/a NTP synchronized: no RTC in local TZ: no DST active: n/a Paimon外部表需要在建表语句中的WITH中通过connector和path表属性来指定。 下面我们来通过具体的案例来演示一下Paimon外部表的使用。 首先来看一下如何在Flink SQL中通过Paimon外部表来读取数据。 创建package:com.imooc.paimon.tabletype 创建object:FlinkSQLReadPaimonExternalTable CREATE TABLE Partition_Table ( id INT, name STRING, dt STRING, hh STRING, PRIMARY KEY (id, dt, hh) NOT ENFORCED ) PARTITIONED BY (dt, hh) WITH( ... ) 然后我们在Paimon Catalog里面创建了两个表:t1和t2。 CREATE TABLE t1(...) WITH (...);

CREATE TEMPORARY TABLE t2( id INT, name STRING ) WITH ( 'connector' = 'filesystem', 'path' = 'hdfs://.../data.json', 'format' = 'json' ); 但是需要注意,后续我们在同时使用表t1和t2的时候,就需要指定表的完整名称了。 类似于FlinkSQLWriteToPaimon这个案例 //向目的地表中写入数据 tEnv.executeSql( """ |INSERT INTO paimon_catalog.default.wc_sink_sql |SELECT | word, | COUNT(*) as cnt |FROM default_catalog.default_database.word_source |GROUP BY word |""".stripMargin).print()

本文到此结束,感谢大家的观看!