/*
* Tencent is pleased to support the open source community by making
* Tencent GT (Version 2.4 and subsequent versions) available.
*
* Notwithstanding anything to the contrary herein, any previous version
* of Tencent GT shall not be subject to the license hereunder.
* All right, title, and interest, including all intellectual property rights,
* in and to the previous version of Tencent GT (including any and all copies thereof)
* shall be owned and retained by Tencent and subject to the license under the
* Tencent GT End User License Agreement (http://gt.qq.com/wp-content/EULA_EN.html).
*
* Copyright (C) 2015 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the MIT License (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of the License at
*
* http://opensource.org/licenses/MIT
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package com.tencent.wstt.gt.log;
import java.util.concurrent.LinkedBlockingQueue;
import com.tencent.wstt.gt.ui.model.CleanLogBuff;
import com.tencent.wstt.gt.ui.model.EndLogBuff;
import com.tencent.wstt.gt.ui.model.LogBuff;
import com.tencent.wstt.gt.ui.model.StartLogBuff;
import com.tencent.wstt.gt.ui.model.ValueBuff;
public class TempLogConsumer {
private static final int CAPACITY = 64;//64;
private static final int CHCHE = 2048;//2048; // 因为java一个空字符串占40字节,每个字符内容占2字节
private LogController controller;
private Thread thread;
private boolean flag;
private LinkedBlockingQueue<LogBuff> queue = new LinkedBlockingQueue<LogBuff>(CAPACITY);
private Thread curLogBuffCheckThread;
private StringBuffer curLogBuff; // 当前log内容缓存
private Object curLogBuffLock;
// 生产者执行队列,专门处理queue.put等阻塞式操作的任务执行器,以免阻塞式操作卡住消费者线程
// private ExecutorService producerExecutor;
TempLogConsumer(final LogController controller) {
this.controller = controller;
curLogBuffLock = new Object();
// producerExecutor = Executors.newSingleThreadExecutor();
thread = new Thread(new Runnable() {
@Override
public void run() {
try {
while (flag) {
LogBuff lb = queue.take();
lb.execute();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}, "TempLogConsumer");
curLogBuff = new StringBuffer(CHCHE);
controller.setTempLogConsumer(this);
curLogBuffCheckThread = new Thread(new Runnable() {
@Override
public void run() {
try {
while (flag) {
// 1s内没新日志,则把缓存送走
Thread.sleep(1000);
synchronized(curLogBuffLock)
{
if (curLogBuff.length() > 0)
{
LogBuff lb = new ValueBuff(curLogBuff, controller);
curLogBuff = new StringBuffer();
queue.offer(lb);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}, TempLogConsumer.this.getClass().getSimpleName() + "$curLogBuffCheckThread");
}
public void start()
{
flag = true;
thread.setPriority(Thread.MIN_PRIORITY);
thread.start();
curLogBuffCheckThread.setPriority(Thread.MIN_PRIORITY);
curLogBuffCheckThread.start();
}
public void stop()
{
flag = false;
}
/**
* LogBuff生产者调用,产生日志,
* 需要加锁的地方是curLogBuff的处理,不过StringBuffer本身就是同步的。同样会操作
* curLogBuff的就是下面startAutoLog等几个方法
* @param content
*/
public void putLog(String content)
{
if (flag && GTLogInternal.isEnable() && GTLogInternal.hasLogNeedIO())
{
synchronized(curLogBuffLock)
{
curLogBuff.append(content);
curLogBuff.append("\r\n");
if (curLogBuff.length() >= CHCHE)
{
LogBuff lb = new ValueBuff(curLogBuff, controller);
curLogBuff = new StringBuffer();
queue.offer(lb);
}
}
}
}
/**
* 由生产者线程调用该方法,开始记录一个日志,主要不要被消费者线程调用了
* @param fileName
*/
public void startALog(String fileName)
{
controller.setTempLogStarting(fileName);
synchronized(curLogBuffLock) {
if (curLogBuff.length() > 0)
{
LogBuff lb = new ValueBuff(curLogBuff, controller);
queue.offer(lb);
curLogBuff = new StringBuffer();
}
}
LogBuff startTag = new StartLogBuff(fileName, controller);
asynPutLogBuff(startTag);
}
public void endALog(String fileName)
{
controller.reudceTempLogStarting(fileName);
synchronized(curLogBuffLock) {
if (curLogBuff.length() > 0)
{
LogBuff lb = new ValueBuff(curLogBuff, controller);
queue.offer(lb);
curLogBuff = new StringBuffer();
}
}
LogBuff endTag = new EndLogBuff(fileName, controller);
asynPutLogBuff(endTag);
}
public void cleanALog(String fileName)
{
synchronized(curLogBuffLock) {
if (curLogBuff.length() > 0)
{
LogBuff lb = new ValueBuff(curLogBuff, controller);
queue.offer(lb);
curLogBuff = new StringBuffer();
}
}
CleanLogBuff cleanTag = new CleanLogBuff(fileName, controller);
asynPutLogBuff(cleanTag);
}
/*
* 为了避免阻塞的put操作死锁,需要单独对put操作异步化并串行处理
*/
private void asynPutLogBuff(final LogBuff lb)
{
try {
queue.put(lb);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}