forked from UCodeUStory/DataStructure
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
bb356e1
commit 7937305
Showing
14 changed files
with
684 additions
and
310 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
7 changes: 7 additions & 0 deletions
7
app/src/main/java/com/wangpos/datastructure/java/semaphore/TestSemaphore.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package com.wangpos.datastructure.java.semaphore | ||
|
||
|
||
fun main() { | ||
|
||
|
||
} |
58 changes: 58 additions & 0 deletions
58
app/src/main/java/com/wangpos/datastructure/java/thread/Helper.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
package com.wangpos.datastructure.java.thread | ||
|
||
import java.util.concurrent.ExecutorService | ||
import java.util.concurrent.Executors | ||
|
||
/** | ||
* Created by Edison Xu on 2017/3/2. | ||
*/ | ||
enum class Helper { | ||
|
||
instance; | ||
|
||
fun run(r: Runnable) { | ||
tPool.submit(r) | ||
} | ||
|
||
fun shutdown() { | ||
tPool.shutdown() | ||
} | ||
|
||
companion object { | ||
|
||
private val tPool = Executors.newFixedThreadPool(2) | ||
|
||
fun buildNoArr(max: Int): Array<String?> { | ||
val noArr = arrayOfNulls<String>(max) | ||
for (i in 0 until max) { | ||
noArr[i] = Integer.toString(i + 1) | ||
} | ||
return noArr | ||
} | ||
|
||
fun buildCharArr(max: Int): Array<String?> { | ||
val charArr = arrayOfNulls<String>(max) | ||
val tmp = 65 | ||
for (i in 0 until max) { | ||
charArr[i] = (tmp + i).toChar().toString() | ||
} | ||
return charArr | ||
} | ||
|
||
@JvmStatic | ||
fun printString(input: String) { | ||
input?.let { | ||
print(input) | ||
} | ||
} | ||
|
||
@JvmStatic | ||
fun print2String(input: String, input2: String) { | ||
if (input == null) | ||
return | ||
print(input) | ||
print(input2) | ||
} | ||
} | ||
|
||
} |
36 changes: 36 additions & 0 deletions
36
app/src/main/java/com/wangpos/datastructure/java/thread/ThreadCommunication.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
package com.wangpos.datastructure.java.thread | ||
|
||
import kotlin.concurrent.thread | ||
|
||
fun main() { | ||
|
||
val messageBridge = MessageBridge() | ||
|
||
thread(true) { | ||
println(messageBridge.doSomeThing()) | ||
} | ||
thread(true) { | ||
println(messageBridge.doSomeThing2()) | ||
|
||
} | ||
|
||
} | ||
|
||
|
||
class MessageBridge { | ||
|
||
var message: Int = 0 | ||
|
||
@Synchronized | ||
fun doSomeThing(): Int { | ||
message++ | ||
return message | ||
} | ||
|
||
@Synchronized | ||
fun doSomeThing2(): Int { | ||
message++ | ||
return message | ||
} | ||
} | ||
|
70 changes: 70 additions & 0 deletions
70
app/src/main/java/com/wangpos/datastructure/java/thread/ThreadCommunication2.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
package com.wangpos.datastructure.java.thread | ||
|
||
import java.util.* | ||
|
||
|
||
fun main() { | ||
val one = MethodOne() | ||
Helper.instance.run(one.newThreadOne()) | ||
Helper.instance.run(one.newThreadTwo()) | ||
Helper.instance.shutdown() | ||
} | ||
|
||
/*8 | ||
1. 第一种解法,包含多种小的不同实现方式,但一个共同点就是靠一个共享变量来做控制; | ||
a. 利用最基本的synchronized、notify、wait: | ||
*/ | ||
|
||
|
||
|
||
class MethodOne { | ||
private val threadToGo = ThreadToGo() | ||
|
||
fun newThreadOne(): Runnable { | ||
val inputArr = Helper.buildNoArr(52) | ||
println(Arrays.toString(inputArr)) | ||
return Runnable { | ||
try { | ||
var i = 0 | ||
while (i < inputArr.size) { | ||
synchronized(threadToGo) { | ||
while (threadToGo.value == 2) | ||
threadToGo.wait() | ||
Helper.print2String(inputArr[i]!!, inputArr[i + 1]!!) | ||
threadToGo.value = 2 | ||
threadToGo.notify() | ||
} | ||
i += 2 | ||
} | ||
} catch (e: InterruptedException) { | ||
println("Oops...") | ||
} | ||
} | ||
} | ||
|
||
fun newThreadTwo(): Runnable { | ||
val inputArr = Helper.buildCharArr(26) | ||
println(Arrays.toString(inputArr)) | ||
return Runnable { | ||
try { | ||
for (i in inputArr.indices) { | ||
synchronized(threadToGo) { | ||
while (threadToGo.value == 1) | ||
threadToGo.wait() | ||
Helper.printString(inputArr[i]!!) | ||
threadToGo.value = 1 | ||
threadToGo.notify() | ||
} | ||
} | ||
} catch (e: InterruptedException) { | ||
println("Oops...") | ||
} | ||
} | ||
} | ||
|
||
internal inner class ThreadToGo:java.lang.Object() { | ||
var value = 1 | ||
} | ||
|
||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
### Android 进程通信方式 | ||
|
||
|
||
一、使用 Intent (startActivity startService sendBroadcast) | ||
二、使用文件共享 (SharePreference) | ||
三、使用 Messenger | ||
四、使用 AIDL | ||
五、使用 ContentProvider | ||
六、使用 Socket | ||
|
||
|
||
|
||
Messenger | ||
|
||
1. Messenger本质也是AIDL,只是进行了封装,开发的时候不用再写.aidl文件。 | ||
结合我自身的使用,因为不用去写.aidl文件,相比起来,Messenger使用起来十分简单。但前面也说了,Messenger本质上也是AIDL,故在底层进程间通信这一块,两者的效率应该是一样的。 | ||
|
||
2. 在service端,Messenger处理client端的请求是单线程的,而AIDL是多线程的。 | ||
使用AIDL的时候,service端每收到一个client端的请求时,就会启动一个线程(非主线程)去执行相应的操作。而Messenger,service收到的请求是放在Handler的MessageQueue里面,Handler大家都用过,它需要绑定一个Thread,然后不断poll message执行相关操作,这个过程是同步执行的。 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
### JDK 1.5 1.8 ConcurrentHashMap 源码剖析 | ||
|
||
|
||
#### ConcurrentHashMap 是一个并发散列映射表的实现,它允许完全并发的读取,并且支持给定数量的并发更新。相比于 HashTable 和同步包装器包装的 HashMap,使用一个全局的锁来同步不同线程间的并发访问,同一时间点,只能有一个线程持有锁,也就是说在同一时间点,只能有一个线程能访问容器,这虽然保证多线程间的安全并发访问,但同时也导致对容器的访问变成串行化的了。 | ||
|
||
1.6中采用ReentrantLock 分段锁的方式,使多个线程在不同的segment上进行写操作不会发现阻塞行为; | ||
|
||
1.8中直接采用了内置锁synchronized,难道是因为1.8的虚拟机对内置锁已经优化的足够快了? | ||
|
||
|
||
1.6 分段锁技术,细粒度划分锁,每一个数据一把锁 | ||
|
||
public class MyConcurrentHashMap<K,V> { | ||
private final int LOCK_COUNT = 16; | ||
private final Map<K,V> map; | ||
private final Object[] locks ; | ||
|
||
public MyConcurrentHashMap() { | ||
this.map = new HashMap<K,V>(); | ||
locks = new Object[LOCK_COUNT]; | ||
for (int i=0;i<LOCK_COUNT;i++){ | ||
locks[i] = new Object(); | ||
} | ||
} | ||
|
||
private int keyHashCode(K k){ | ||
return Math.abs(k.hashCode() % LOCK_COUNT); | ||
} | ||
|
||
public V get(K k){ | ||
int keyHashCode = keyHashCode(k); | ||
synchronized (locks[keyHashCode % LOCK_COUNT]){ | ||
return map.get(k); | ||
} | ||
} | ||
|
||
} | ||
|
||
|
||
1.8 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
### |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
|
||
|
||
### 比较难读的英文单词 | ||
|
||
- synchronized | ||
|
||
- AsyncTask | ||
|
||
- semaphore | ||
|
||
- reentrantLock | ||
|
||
- concurrentHashMap | ||
|
||
- condition | ||
|
||
- segment | ||
|
||
- volatile | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
|
||
### 分段加锁思想。 | ||
|
||
|
||
**电商公司:假如下单时,用分布式锁来防止库存超卖,但是是每秒上千订单的高并发场景,如何对分布式锁进行高并发优化来应对这个场景? | ||
在实际落地生产的时候,分布式锁这个东西保证了数据的准确性,但是他天然并发能力有点弱** | ||
|
||
|
||
假如你现在iphone有1000个库存,那么你完全可以给拆成20个库存段,要是你愿意,可以在数据库的表里建20个库存字段,每个库存段是50件库存,比如stock_01对应50件库存,stock_02对应50件库存。类似这样的,也可以在redis之类的地方放20个库存key。 | ||
|
||
接着,1000个/s 请求,用一个简单的随机算法,每个请求都是随机在20个分段库存里,选择一个进行加锁。 | ||
|
||
每个下单请求锁了一个库存分段,然后在业务逻辑里面,就对数据库或者是Redis中的那个分段库存进行操作即可,包括查库存 -> 判断库存是否充足 -> 扣减库存。 | ||
|
||
相当于一个20毫秒,可以并发处理掉20个下单请求,那么1秒,也就可以依次处理掉20 * 50 = 1000个对iphone的下单请求了。 | ||
|
||
一旦对某个数据做了分段处理之后,有一个坑一定要注意:就是如果某个下单请求,咔嚓加锁,然后发现这个分段库存里的库存不足了,此时咋办? | ||
|
||
这时你得自动释放锁,然后立马换下一个分段库存,再次尝试加锁后尝试处理。 这个过程一定要实现。 | ||
|
||
#### 分布式锁并发优化方案的不足 | ||
|
||
最大的不足,很不方便,实现太复杂。 | ||
|
||
- 首先,你得对一个数据分段存储,一个库存字段本来好好的,现在要分为20个分段库存字段; | ||
- 其次,你在每次处理库存的时候,还得自己写随机算法,随机挑选一个分段来处理; | ||
- 最后,如果某个分段中的数据不足了,你还得自动切换到下一个分段数据去处理。 | ||
这个过程都是要手动写代码实现的,还是有点工作量,挺麻烦的。 | ||
|
||
不过我们确实在一些业务场景里,因为用到了分布式锁,然后又必须要进行锁并发的优化,又进一步用到了分段加锁的技术方案,效果当然是很好的了,一下子并发性能可以增长几十倍 |
Oops, something went wrong.