Browse Source

map的遍历

rz 2 năm trước cách đây
mục cha
commit
df23a48f46
4 tập tin đã thay đổi với 66 bổ sung5 xóa
  1. 4 1
      go.mod
  2. 2 0
      go.sum
  3. 33 2
      map.go
  4. 27 2
      map_test.go

+ 4 - 1
go.mod

@@ -2,4 +2,7 @@ module jconcurrency
 
 go 1.19
 
-require github.com/panjf2000/ants/v2 v2.6.0
+require (
+	github.com/orcaman/concurrent-map/v2 v2.0.1
+	github.com/panjf2000/ants/v2 v2.6.0
+)

+ 2 - 0
go.sum

@@ -1,4 +1,6 @@
 github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
+github.com/orcaman/concurrent-map/v2 v2.0.1 h1:jOJ5Pg2w1oeB6PeDurIYf6k9PQ+aTITr/6lP/L/zp6c=
+github.com/orcaman/concurrent-map/v2 v2.0.1/go.mod h1:9Eq3TG2oBe5FirmYWQfYO5iH1q0Jv47PLaNK++uCdOM=
 github.com/panjf2000/ants/v2 v2.6.0 h1:xOSpw42m+BMiJ2I33we7h6fYzG4DAlpE1xyI7VS2gxU=
 github.com/panjf2000/ants/v2 v2.6.0/go.mod h1:cU93usDlihJZ5CfRGNDYsiBYvoilLvBF5Qp/BT2GNRE=
 github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=

+ 33 - 2
map.go

@@ -4,7 +4,7 @@ import (
 	"sync"
 )
 
-//HashMap对象,安全操作
+//HashMap对象,局限安全操作,对外暴露了锁和数据,在自行遍历如果再加锁就会死锁!
 type JyMap struct {
 	Lock sync.RWMutex
 	Data map[any]any
@@ -55,8 +55,39 @@ func (jm *JyMap) SetIfNoExists(k, v any) {
 }
 
 //map中是否存在
-func (jm *JyMap) IsExists(k any) bool {
+func (jm *JyMap) Has(k any) bool {
 	jm.Lock.RLock()
 	defer jm.Lock.RUnlock()
 	return jm.Data[k] != nil
 }
+
+//长度
+func (jm *JyMap) Len() int {
+	jm.Lock.RLock()
+	defer jm.Lock.RUnlock()
+	return len(jm.Data)
+}
+
+//如果不使用此方法遍历,再调用自身的方法加锁,就会死锁
+//目前没有找到好的解决办法,只有自己控制好,特别是遍历的时候同时修改map
+func (jm *JyMap) Iter(fn func(k, v any) bool) {
+	jm.Lock.RLock()
+	ch := make(chan []any, len(jm.Data))
+	go func() {
+	L1:
+		for {
+			select {
+			case arr, ok := <-ch:
+				if !fn(arr[0], arr[1]) || !ok {
+					_ = ch
+					break L1
+				}
+			}
+		}
+	}()
+	for k, v := range jm.Data {
+		ch <- []any{k, v}
+	}
+	close(ch)
+	jm.Lock.RUnlock()
+}

+ 27 - 2
map_test.go

@@ -3,6 +3,8 @@ package jconcurrency
 import (
 	"log"
 	"testing"
+	"time"
+	//"github.com/orcaman/concurrent-map/v2"
 )
 
 func Test_map(t *testing.T) {
@@ -12,10 +14,10 @@ func Test_map(t *testing.T) {
 	jm.Set("a", 1)
 	jm.Set(1, 3)
 	//判断值是否存在
-	log.Println("key 1 :", jm.IsExists(1))
+	log.Println("key 1 :", jm.Has(1))
 	//删除值
 	jm.Del(1)
-	log.Println("key 1 :", jm.IsExists(1))
+	log.Println("key 1 :", jm.Has(1))
 	//如果不存在则放入
 	jm.SetIfNoExists("a", 5)
 	jm.SetIfNoExists("b", 6)
@@ -23,3 +25,26 @@ func Test_map(t *testing.T) {
 	log.Println(jm.GetAndDel("b"))
 	log.Println(jm)
 }
+
+func Test_map2(t *testing.T) {
+
+	jm := NewJM()
+	for i := 0; i < 100000; i++ {
+		jm.Set(i, i)
+	}
+
+	for i := 0; i < 2; i++ {
+		go jm.Iter(func(k, v any) bool {
+			if k == i {
+				//暂停
+				return false
+			}
+			return true
+		})
+	}
+
+	time.Sleep(1 * time.Second)
+
+	log.Println(jm.Len())
+
+}