我有一个方法fetchAndMoveMessageInfo,它将被多个线程并发访问,它执行以下操作:
对于第二个要求,我使用了ConcurrentLinkedQueue来确保没有线程弹出相同的项目。
对于第一个要求,我使用了ReentrantLock Lock,以便获取写锁定的线程应该执行db read ops以填充其他读取器应该等待缓存填充。填充缓存后,读取同时对队列进行线程化。
我有以下查询:
我的上述设计可以吗?但我观察到,当dbinfo中的messageinfo计数减少时,随着messageinfos数量下降,吞吐量急剧下降。我认为这是因为当messsgeInofs较少时,争用和更多数量的db读取。例如,如果writer获取600 messageInfos,那么所有其他线程将从缓存中获得599的剩余部分。但是如果编写器(获取写锁定并从数据库读取的那个)只提取了2条消息,则消息数量会减少。这将导致争用和更多数量的数据库查询。我的疑问是正确的吗?我是否必须忍受这种情况,还是有更好的方法来处理这个问题?
我还观察到一个同步的方法的争用,并且只能调用getDequeueMessageInfo。我不知道当ReentrantLock锁定在一次只有作者时,这个方法如何得到争用。
有没有更好的设计?请提出建议。
以下是我的代码和JFR争用快照的快照。
Sub GetSheets()
Dim sFileName As String
Dim Path As String
Dim wbNew As Workbook
Dim tmpWb As Workbook
Dim tSheets As Long
Dim iSheets As Long
iSheets = 0
Set wbNew = gWrkBook() 'creat new workbook
Path = gGetFolder("Any default folder path")
If gSearch(Path, "\", "LastChar") > 0 Then
Path = Path + "\"
End If
Filename = dir(Path & "*.xlsx")
Do While Filename <> ""
Workbooks.Open Filename:=Path & Filename, ReadOnly:=True
Set tmpWb = ActiveWorkbook
tSheets = tmpWb.Worksheets.Count
If tSheets > 0 Then
iSheets = 1
tmpWb.Sheets(iSheets).Activate
For iSheets = 1 To tSheets
tmpWb.Sheets(iSheets).Activate
Range("A2").Select
If Range("A2").Value <> "" Then
sFileName = tmpWb.Name + "-" + CStr(iSheets)
sFileName = Replace(sFileName, ".xlsx", "")
tmpWb.Sheets(iSheets).Name = sFileName
wbNew.Activate
tmpWb.Sheets(iSheets).Copy After:=wbNew.Sheets(1)
Else
End If
tmpWb.Activate
Next
End If
Workbooks(Filename).Close savechanges:=False
Filename = dir()
Loop
End Sub
Public Function gGetFolder(strPath As String) As String
Dim fldr As FileDialog
Set fldr = Application.FileDialog(msoFileDialogFolderPicker)
With fldr
.Title = "Select a Folder"
.AllowMultiSelect = False
.InitialFileName = strPath
If .Show <> -1 Then GoTo NextCode
sItem = .SelectedItems(1)
End With
NextCode:
gGetFolder = sItem
Set fldr = Nothing
End Function