Nicksxs's Blog

What hurts more, the pain of hard work or the pain of regret?

上周因为一些事情没回去,买好了内存条这周才回去用,结果不知道是 U 盘的问题还是什么其他原因原来装的那个系统起不来,然后想用之前一直用的 LD 的笔记本,结果 LD 的老笔记本也起不来了,一直卡在启动界面,猜测可能是本身也比较老了,用的机械硬盘会不会被我一直动而损坏了,所以就想搞个老毛桃跟新搞一个启动盘,结果这周最大的坑就在这了,在我的 15 寸 mbp 上用etcher做了个 win10 的启动盘,可能是分区表格式是 GUID,不是 MBR 的,老电脑不能识别,就像装个虚拟机来做启动盘,结果像老毛桃不支持这种用虚拟机的,需要本地磁盘,然后我就有用 bootcamp 安装了个 win10,又没网络,查了下网络需要用 bootcamp 下载 Windows Support 软件,下了好久一直没下完,后来又提示连不上苹果服务器,好不容易下完了,开启 win10 后,安装到一半就蓝屏了,真的是够操蛋的,在这个时候真的很需要有一个 Windows 机器的支持,LD 的那个笔记本也跟我差不多老了,虽然比较慢但之前好歹也还可以用,结果这下也被我弄坏了,家里就没有其他机器可以支持了,有点巧妇难为无米之炊的赶脚,而且还是想再折腾下我的老电脑,后面看看打算做几个 U 盘,分工职责明确,一个老毛桃的PE 盘,老毛桃的虽然不是很纯净的,但是是我一直以来用过内置工具比较全,修复启动功能比较强大的一个 pe,没用过 winpe,后续可以考虑使用下,一个 win7 的启动盘,因为是老电脑,如果后面是新的电脑可以考虑是 win10,一个 win to go 盘,这样我的 mbp 就可以直接用 win10 了,不过想来也还是要有一台 win 机器才比较好,不然很多时候都是在折腾工具,工欲善其事必先利其器,后面也可以考虑能够更深入的去了解主板的一些问题,我原来的那个主板可能是一些小的电阻等问题,如果能自己学习解决就更好了,有时候研究下还是有意思的。

连接池主要是两个逻辑,首先是获取连接的逻辑,结合代码来讲一讲

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
private PooledConnection popConnection(String username, String password) throws SQLException {
boolean countedWait = false;
PooledConnection conn = null;
long t = System.currentTimeMillis();
int localBadConnectionCount = 0;

// 循环获取连接
while (conn == null) {
// 加锁
lock.lock();
try {
// 如果闲置的连接列表不为空
if (!state.idleConnections.isEmpty()) {
// Pool has available connection
// 连接池有可用的连接
conn = state.idleConnections.remove(0);
if (log.isDebugEnabled()) {
log.debug("Checked out connection " + conn.getRealHashCode() + " from pool.");
}
} else {
// Pool does not have available connection
// 进入这个分支表示没有空闲连接,但是活跃连接数还没达到最大活跃连接数上限,那么这时候就可以创建一个新连接
if (state.activeConnections.size() < poolMaximumActiveConnections) {
// Can create new connection
// 这里创建连接我们之前讲过,
conn = new PooledConnection(dataSource.getConnection(), this);
if (log.isDebugEnabled()) {
log.debug("Created connection " + conn.getRealHashCode() + ".");
}
} else {
// Cannot create new connection
// 进到这个分支了就表示没法创建新连接了,那么怎么办呢,这里引入了一个 poolMaximumCheckoutTime,这代表了我去控制连接一次被使用的最长时间,如果超过这个时间了,我就要去关闭失效它
PooledConnection oldestActiveConnection = state.activeConnections.get(0);
long longestCheckoutTime = oldestActiveConnection.getCheckoutTime();
if (longestCheckoutTime > poolMaximumCheckoutTime) {
// Can claim overdue connection
// 所有超时连接从池中被借出的次数+1
state.claimedOverdueConnectionCount++;
// 所有超时连接从池中被借出并归还的时间总和 + 当前连接借出时间
state.accumulatedCheckoutTimeOfOverdueConnections += longestCheckoutTime;
// 所有连接从池中被借出并归还的时间总和 + 当前连接借出时间
state.accumulatedCheckoutTime += longestCheckoutTime;
// 从活跃连接数中移除此连接
state.activeConnections.remove(oldestActiveConnection);
// 如果该连接不是自动提交的,则尝试回滚
if (!oldestActiveConnection.getRealConnection().getAutoCommit()) {
try {
oldestActiveConnection.getRealConnection().rollback();
} catch (SQLException e) {
/*
Just log a message for debug and continue to execute the following
statement like nothing happened.
Wrap the bad connection with a new PooledConnection, this will help
to not interrupt current executing thread and give current thread a
chance to join the next competition for another valid/good database
connection. At the end of this loop, bad {@link @conn} will be set as null.
*/
log.debug("Bad connection. Could not roll back");
}
}
// 用此连接的真实连接再创建一个连接,并设置时间
conn = new PooledConnection(oldestActiveConnection.getRealConnection(), this);
conn.setCreatedTimestamp(oldestActiveConnection.getCreatedTimestamp());
conn.setLastUsedTimestamp(oldestActiveConnection.getLastUsedTimestamp());
oldestActiveConnection.invalidate();
if (log.isDebugEnabled()) {
log.debug("Claimed overdue connection " + conn.getRealHashCode() + ".");
}
} else {
// Must wait
// 这样还是获取不到连接就只能等待了
try {
// 标记状态,然后把等待计数+1
if (!countedWait) {
state.hadToWaitCount++;
countedWait = true;
}
if (log.isDebugEnabled()) {
log.debug("Waiting as long as " + poolTimeToWait + " milliseconds for connection.");
}
long wt = System.currentTimeMillis();
// 等待 poolTimeToWait 时间
condition.await(poolTimeToWait, TimeUnit.MILLISECONDS);
// 记录等待时间
state.accumulatedWaitTime += System.currentTimeMillis() - wt;
} catch (InterruptedException e) {
// set interrupt flag
Thread.currentThread().interrupt();
break;
}
}
}
}
// 如果连接不为空
if (conn != null) {
// ping to server and check the connection is valid or not
// 判断是否有效
if (conn.isValid()) {
if (!conn.getRealConnection().getAutoCommit()) {
// 回滚未提交的
conn.getRealConnection().rollback();
}
conn.setConnectionTypeCode(assembleConnectionTypeCode(dataSource.getUrl(), username, password));
// 设置时间
conn.setCheckoutTimestamp(System.currentTimeMillis());
conn.setLastUsedTimestamp(System.currentTimeMillis());
// 添加进活跃连接
state.activeConnections.add(conn);
state.requestCount++;
state.accumulatedRequestTime += System.currentTimeMillis() - t;
} else {
if (log.isDebugEnabled()) {
log.debug("A bad connection (" + conn.getRealHashCode() + ") was returned from the pool, getting another connection.");
}
// 连接无效,坏连接+1
state.badConnectionCount++;
localBadConnectionCount++;
conn = null;
// 如果坏连接已经超过了容忍上限,就抛异常
if (localBadConnectionCount > (poolMaximumIdleConnections + poolMaximumLocalBadConnectionTolerance)) {
if (log.isDebugEnabled()) {
log.debug("PooledDataSource: Could not get a good connection to the database.");
}
throw new SQLException("PooledDataSource: Could not get a good connection to the database.");
}
}
}
} finally {
// 释放锁
lock.unlock();
}

}

if (conn == null) {
// 连接仍为空
if (log.isDebugEnabled()) {
log.debug("PooledDataSource: Unknown severe error condition. The connection pool returned a null connection.");
}
// 抛出异常
throw new SQLException("PooledDataSource: Unknown severe error condition. The connection pool returned a null connection.");
}
// fanhui
return conn;
}

然后是还回连接

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
protected void pushConnection(PooledConnection conn) throws SQLException {
// 加锁
lock.lock();
try {
// 从活跃连接中移除当前连接
state.activeConnections.remove(conn);
if (conn.isValid()) {
// 当前的空闲连接数小于连接池中允许的最大空闲连接数
if (state.idleConnections.size() < poolMaximumIdleConnections && conn.getConnectionTypeCode() == expectedConnectionTypeCode) {
// 记录借出时间
state.accumulatedCheckoutTime += conn.getCheckoutTime();
if (!conn.getRealConnection().getAutoCommit()) {
// 同样是做回滚
conn.getRealConnection().rollback();
}
// 新建一个连接
PooledConnection newConn = new PooledConnection(conn.getRealConnection(), this);
// 加入到空闲连接列表中
state.idleConnections.add(newConn);
newConn.setCreatedTimestamp(conn.getCreatedTimestamp());
newConn.setLastUsedTimestamp(conn.getLastUsedTimestamp());
// 原连接失效
conn.invalidate();
if (log.isDebugEnabled()) {
log.debug("Returned connection " + newConn.getRealHashCode() + " to pool.");
}
// 提醒前面等待的
condition.signal();
} else {
// 上面是相同的,就是这里是空闲连接数已经超过上限
state.accumulatedCheckoutTime += conn.getCheckoutTime();
if (!conn.getRealConnection().getAutoCommit()) {
conn.getRealConnection().rollback();
}
conn.getRealConnection().close();
if (log.isDebugEnabled()) {
log.debug("Closed connection " + conn.getRealHashCode() + ".");
}
conn.invalidate();
}
} else {
if (log.isDebugEnabled()) {
log.debug("A bad connection (" + conn.getRealHashCode() + ") attempted to return to the pool, discarding connection.");
}
state.badConnectionCount++;
}
} finally {
lock.unlock();
}
}

接着上一篇的折腾记,因为这周又尝试了一些新的措施和方法,想继续记录分享下,上周的整体情况大概是 Ubuntu 系统能进去了,但是 Windows 进不去,PE 也进不去,Windows 启动盘也进不去,因为我的机器加过一个 msata 的固态,Windows 是装在 msata 固态硬盘里的,Ubuntu 是装在机械硬盘里的,所以有了一种猜测就是可能这个固态硬盘有点问题,还有就是还是怀疑内存的问题,正好家里还有个msata 的固态硬盘,是以前想给LD 的旧笔记本换上的,因为买回来放在那没有及时装,后面会又找不到,直到很后面才找到,LD 也不怎么用那个笔记本了,所以就一直放着了,这次我就想拿来换上。
周末回家我就开始尝试了,换上了新的固态硬盘后,插上 Windows 启动 U 盘,这次一开始看起来有点顺利,在 BIOS 选择 U 盘启动,进入了 Windows 安装界面,但是装到一半,后面重启了之后就一直说硬盘有问题,让重启,但是重启并没有解决问题,变成了一直无效地重复重启,再想进 U 盘启动,就又进不去了,这时候怎么说呢,感觉硬盘不是没有问题,但是呢,问题应该不完全出在这,所以按着总体的逻辑来讲,主板带着cpu 跟显卡,都换掉了,硬盘也换掉了,剩下的就是内存了,可是内存我也尝试过把后面加的那条金士顿拔掉,可还是一样,也尝试过用橡皮擦金手指,这里感觉也很奇怪了,找了一圈了都感觉没啥明确的原因,比如其实我的猜测,主板电池的问题,一些电阻坏掉了,但是主板是换过的,那如果内存有问题,照理我用原装的那条应该会没问题,也有一种非常小的可能,就是两条内存都坏了,或者说这也是一种不太可能的可能,所以最后的办法就打算试试把两条内存都换掉,不过现在网上都找不到这个内存的确切信息了,只能根据大致的型号去买来试试,就怕买来的还是坏的,其实也怕是这个买来的主板因为也是别的拆机下来的,不一定保证完全没问题,要是有类似的问题或者也有别的问题导致开不起来就很尴尬,也没有很多专业的仪器可以排查原因,比如主板有没有什么短路的,对了还有一个就是电源问题,但是电源的问题也就可能是从充电器插的口子到主板的连线,因为 LD 的电源跟我的口子一样,也试过,但是结果还是一样,顺着正常逻辑排查,目前也没有剩下很明确的方向了,只能再尝试下看看。

上大学的时候买了第一个笔记本,是联想的小y,y460,配置应该是 i5+2g 内存,500g 硬盘,ati 5650 的显卡,那时候还是比较时髦的带有集显和独显切换的,一些人也觉得它算是一代“神机”,陪我度过了大学四年,还有毕业后的第一年,记得中间还用的比较曲折,差不多第一学期末的时候硬盘感觉有时候会文件操作卡住,去售后看了下,果然硬盘出问题了,还在当场把硬盘的东西都拷贝到新买的移动硬盘里,不过联想的售后还是比较不错的,在保内可以直接免费换,如果出保了估计就要修不起了,后面出了个很大的问题,就是屏幕花屏了,而且它的花屏是横着的会有那种上升的变化,一开始感觉跟湿度还有温度有点关系,天气冷了就很容易出现,天气热了就好一点,出现的概率小一点,而且是合盖后再开会好,过一会又会上升,只是这么度过了保修期,去售后问了下,修一下要两千多,后来是在玉泉学校里面的维修店,好像是花了六百多,省是省了很多,但是后面使用的时候发现有点漏光,而且两三个亮点,总归还是给我那不富裕的经济条件带来了一个正常屏幕,不过是挺影响使用,严格来说都没法用了,后面基本是大半个屏幕花掉,接近整个屏幕花掉,至此大学就是这么用过去了。
噢对了,中间在大二的时候加了一条 2g 的内存,因为像操作系统课需要用虚拟机,2g 内存不太够,不过那会用的都是 32 位的 win7 系统,实际使用用不到 4g 内存,得使用破解补丁才能识别到,后来在大学毕业后由于收入也低,想换其他电脑,特别是 mac,买不起,电脑在那会还会玩玩 DNF,但是风扇声很大,也想优化下,就买了个 msata 的固态硬盘,因为刚好有个口子留着,在那之前一直搜到的是把光驱位拆掉换上 sata 固态硬盘,这对于那会的我来说操作难度实在有点大,换上了msata 固态之后还是有比较大的提升的,把操作系统装到固态硬盘后其他盘就只放数据了,后面还装过黑苹果,只是不小心被室友强制关机了,之后就起不来了,也不知道啥原因,后续想继续按原来的操作装,也没成功,再往后就配了一台台式机,这个笔记本就放在那没啥用了,后面偶尔会拿出来用一下,特别是疫情那会充当了 LD 的临时使用机器。
最近一次就是想把行车记录仪里的视频导出来,结果上传的时候我点了下 win10 的更新,重启后这个机器就起不来了,一开始以为顶多是个重装系统,结果重装也不行,就进不去,插着 U 盘也起不来,一开始还能进 BIOS,后面就直接进不去了,像内存条脏了,擦下金手指什么的,都没搞定,想着也只可能是主板上的部件坏了,所以就开始了这趟半作死之旅,买了块主板来换,拆这个笔记本是真的够难的,开机键那一条是真的拆不开,后面还把两个扣子扳坏了,里面的排线插口还几个也拔坏了,幸好用买来的主板装上还能用,但是后面就很奇怪了,因为这个电脑装了 Ubuntu 跟 win10 的双系统,Ubuntu 能正常起来,但是 win10 就是起不来,插上老毛桃或者 win10 的启动盘都是起不来,老毛桃是能起来,但是进不了 pe,插启动盘又报 0xc00000e9 错误码,现在想着是不是这个固态硬盘有点问题或者还是内存问题,只能后续再看了,拆机的时候也找不到视频,机器实在是太老了,后面再试试看。

作为一个 Windows 的老用户,并且也算是 Windows 系统的半个粉丝,但是秉承一贯的优缺点都应该说的原则,Windows 系统有一点缺点是真的挺难受,相信 Windows 用过比较久的都会经历过,就是 U盘无法退出的问题,在比较远古时代,这个问题似乎能采取的措施不多,关机再拔 U盘的方式是一种比较保险的方式,其他貌似有 360这种可以解除占用的,但是需要安装 360 软件,对于目前的使用环境来说有点得不偿失,也是比较流氓的一类软件了,目前在 Windows 环境我主要就安装了个火绒,或者就用 Windows 自带的 defender。

第一种

最近这次经历也是有火绒的一定责任,在我尝试推出 U盘的时候提示了我被另一个大流氓软件,XlibabaProtect.exe 占用了,这个流氓软件真的是充分展示了某里的技术实力,试过 N 多种办法都关不掉也删不掉,尝试了很多种办法也没办法删除,但是后面换了种思路,一般这种情况肯定是有进程在占用 U盘里的内容,最新版本的 Powertoys 会在文件的右键菜单里添加一个叫 File Locksmith 的功能,可以用于检查正在使用哪些文件以及由哪些进程使用,但是可能是我的使用姿势不对,没有仔细看文档,它里面有个”以管理员身份重启”,可能会有用。
这算是第一种方式,

第二种

第二种方式是 Windows 任务管理器中性能 tab 下的”打开资源监视器”,
,假如我的 U 盘的盘符是F:
就可以搜索到占用这个盘符下文件的进程,这里千万小心‼️‼️,不可轻易杀掉这些进程,有些系统进程如果轻易杀掉会导致蓝屏等问题,不可轻易尝试,除非能确认这些进程的作用。
对于前两种方式对我来说都无效,

第三种

所以尝试了第三种,
就是磁盘脱机的方式,在”计算机”右键管理,点击”磁盘管理”,可以找到 U 盘盘符右键,点击”脱机”,然后再”推出”,这个对我来说也不行

第四种

这种是唯一对我有效的,在开始菜单搜索”event”,可以搜到”事件查看器”,
,这个可以看到当前最近 Windows 发生的事件,打开这个后就点击U盘推出,因为推不出来也是一种错误事件,点击下刷新就能在这看到具体是因为什么推出不了,具体的进程信息
最后发现是英特尔的驱动管理程序的一个进程,关掉就退出了,虽然前面说的某里的进程是流氓,但这边是真的冤枉它了

0%