gpt4 book ai didi

java - Android:如何创建二维数组的副本以在另一个线程中使用?

转载 作者:行者123 更新时间:2023-12-01 14:12:26 25 4
gpt4 key购买 nike

我创建了一个基本的日志记录类,其中当前是一个二维数组,最多存储 100 个事件的日志信息(然后开始覆盖信息,因此我只保留最后 100 个事件)。

在某个级别的日志事件上,该数组数据将转储到 AsyncTask 线程上的数据库中。

目前,该数组是在类级别定义的,因此 AsyncTask 线程正在访问 GUI 线程正在访问的同一数组(这给了我 NullPointerExceptions,因为它应该)。

我需要一种方法来复制 AsyncTask 线程启动时的数组值,以便该后台线程可以读取所有数据并将其正确发送到数据库 - 这就是重点我被困在了。

// Defined in the class
private static String[][] logHistory = new String[100][6];


// Class to log errors to a database
private static class asyncLog extends AsyncTask<Void,Void,Void>
{
// This is the background thread
@Override
protected Void doInBackground(Void... params)
{
Thread.currentThread().setName("LogToDB.asyncLog.doInBackground");

// Make a copy of the array in its current state
final String[][] logTemp = new String[100][6];
for (int i = 0; i < 100; i++)
{
for (int j = 0; j < 6; j++)
{
logTemp[i][j]=logHistory[i][j];
}
}

// ...snip
}
}

显然这里的final修饰符是错误的,因为我仍然遇到异常

我想知道:

  • 这是做我想做的事情的正确方法吗?
  • 如果没有,什么是更好的方法?
  • 如何在后台线程中复制字符串数组,以便无论 GUI 线程对原始数组进行什么更改,副本始终具有相同的值,直到线程结束并被销毁

我见过很多处理一维数组的例子,但这些大多是 int 数据类型(例如 this one ,据我了解字符串,它们始终是引用:/

编辑根据要求,请参阅堆栈跟踪:

08-23 09:17:35.570: E/AndroidRuntime(8030): FATAL EXCEPTION: LogToDB.asyncLog.doInBackground
08-23 09:17:35.570: E/AndroidRuntime(8030): java.lang.RuntimeException: An error occured while executing doInBackground()
08-23 09:17:35.570: E/AndroidRuntime(8030): at android.os.AsyncTask$3.done(AsyncTask.java:299)
08-23 09:17:35.570: E/AndroidRuntime(8030): at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:352)
08-23 09:17:35.570: E/AndroidRuntime(8030): at java.util.concurrent.FutureTask.setException(FutureTask.java:219)
08-23 09:17:35.570: E/AndroidRuntime(8030): at java.util.concurrent.FutureTask.run(FutureTask.java:239)
08-23 09:17:35.570: E/AndroidRuntime(8030): at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
08-23 09:17:35.570: E/AndroidRuntime(8030): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
08-23 09:17:35.570: E/AndroidRuntime(8030): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
08-23 09:17:35.570: E/AndroidRuntime(8030): at java.lang.Thread.run(Thread.java:856)
08-23 09:17:35.570: E/AndroidRuntime(8030): Caused by: java.lang.NullPointerException
08-23 09:17:35.570: E/AndroidRuntime(8030): at coty.production.downtimeaquisition.LogToDB.Insert(LogToDB.java:393)
08-23 09:17:35.570: E/AndroidRuntime(8030): at coty.production.downtimeaquisition.LogToDB.access$10(LogToDB.java:387)
08-23 09:17:35.570: E/AndroidRuntime(8030): at coty.production.downtimeaquisition.LogToDB$asyncLog.doInBackground(LogToDB.java:558)
08-23 09:17:35.570: E/AndroidRuntime(8030): at coty.production.downtimeaquisition.LogToDB$asyncLog.doInBackground(LogToDB.java:1)
08-23 09:17:35.570: E/AndroidRuntime(8030): at android.os.AsyncTask$2.call(AsyncTask.java:287)
08-23 09:17:35.570: E/AndroidRuntime(8030): at java.util.concurrent.FutureTask.run(FutureTask.java:234)
08-23 09:17:35.570: E/AndroidRuntime(8030): ... 4 more

LogToDB.java:558是对Insert方法的调用

LogToDB.java:387 是插入方法

LogToDB.java:393 是突出显示的行:

Statement stmt=null;

try
{
stmt=dbConn.createStatement(); // This line
stmt.executeUpdate(sql);
}

最佳答案

我假设您想要做的是拥有一个事件的“虚拟日志”,只有在出现某些不良情况时才会转储,这样您就不会弄乱您的主日志但每当发生错误时都可以看到详细信息。如果是这样的话,我会这样做:

  1. 定义一个类LogMessage,其中包含有关消息的必要信息,通常是String和日志级别(应该是enum) ,可能带有一个 Throwable 字段。请参阅 log4j 和 slf4j 以获取此界面通常外观的示例。
  2. 定义一个固定长度的缓冲区类;不幸的是,虽然 1.6 并发 API 有支持固定长度队列的接口(interface),但我无法找到一个好的、高效的实现。最佳选择很大程度上取决于读取和转储的频率,但我首先会做一些事情,例如分配固定大小的数组,使用 AtomicInteger 作为数组索引。标准(无限大小)实现基于 the paper "Simple, Fast, and Practical Non-Blocking and Blocking Concurrent Queue Algorithms" 。对此数组的引用需要是 volatile 或由AtomicReference支持。
  3. 当跟踪日志级别的“漏斗”API 看到具有适当重要性的日志消息时,它会自动交换整个日志结构并启动一个作业来转储它。如果您正在记录的设施会被多个日志线程混淆,您甚至可以将整个日志缓冲区提交到单个长时间运行的转储线程从中读取的 BlockingQueue 中。

关于java - Android:如何创建二维数组的副本以在另一个线程中使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18397832/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com