资料地址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()
本文到此结束,感谢大家的观看!