Это обсуждается в учебнике Oracle Определение и запуск потока :
Какую из этих идиом вы должны использовать? Первая идиома, которая использует объект Runnable, является более общей, поскольку объект Runnable может подклассифицировать класс, отличный от Thread. Вторая идиома проста в использовании в простых приложениях, но ограничена тем, что ваш класс задачи должен быть потомком Thread. В этом уроке основное внимание уделяется первому подходу, который отделяет задачу Runnable от объекта Thread, выполняющего задачу. Этот подход не только более гибкий, но применим к API-интерфейсам управления потоками высокого уровня, рассмотренным позже.
Другими словами, реализация
Runnable
будет работать в сценариях, где ваш класс расширяется класс, отличный отThread
. Java не поддерживает множественное наследование. Кроме того, расширениеThread
не будет возможно при использовании некоторых высокоуровневых API управления потоками. Единственный сценарий, когда расширениеThread
предпочтительнее, - это небольшое приложение, которое в будущем не будет обновляться. Практически лучше реализоватьRunnable
, поскольку он более гибкий по мере роста вашего проекта. Изменение дизайна не окажет большого влияния, поскольку вы можете реализовать множество интерфейсов в java, но только расширить один класс.
Решение 1
Пример кода; это не лучшая или самая короткая реализация, но она ясна и понятна для начинающих программистов.
string[] arr = { "1", "2", "3", "4", "5", "6", "7" };
int rowCount = arr.Length / dt.Columns.Count;
for (int rowIndex = 0; rowIndex < rowCount; rowIndex++)
{
DataRow row = dt.NewRow();
for (int columnIndex = 0; columnIndex < dt.Columns.Count; columnIndex++)
{
// In case of 2 rows:
// row 1: (0 * 4) + 0 = 0
// row 1: (0 * 4) + 1 = 1
// row 1: (0 * 4) + 2 = 2
// row 1: (0 * 4) + 3 = 3
// row 2: (1 * 4) + 0 = 4
// row 2: (1 * 4) + 1 = 5
// row 2: (1 * 4) + 2 = 6
// row 2: (1 * 4) + 3 = 7
row[columnIndex] = arr[(rowIndex * dt.Columns.Count) + columnIndex];
}
dt.Rows.Add(row);
}
Решение 2
Более усовершенствованное и безопасное для края решение , которое использует методы расширения для разделения исходного массива на несколько подмассивов и заполнения таблицы данных.
public static class Extensions
{
public static IEnumerable<IEnumerable<T>> Split<T>(this T[] array, int size)
{
for (var i = 0; i < (float)array.Length / size; i++)
{
yield return array.Skip(i * size).Take(size);
}
}
public static void FillDataTable<T>(this DataTable dataTable, T[] input)
{
IEnumerable<IEnumerable<T>> rowValues = input.Split(dataTable.Columns.Count);
foreach (IEnumerable<T> rowValue in rowValues)
{
DataRow row = dataTable.NewRow();
T[] cellValues = rowValue.ToArray();
for (int columnIndex = 0; columnIndex < cellValues.Length; columnIndex++)
{
// 'Safe'-check in case the original array didn't contain enough values. The cell value will remain 'null'
if (columnIndex < dataTable.Columns.Count)
{
row[columnIndex] = cellValues[columnIndex];
}
}
dataTable.Rows.Add(row);
}
}
}
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
int[] input = { 1, 2, 3, 4, 5, 6, 7, 8 };
DataTable dataTable = new DataTable();
dataTable.Columns.Add("v1");
dataTable.Columns.Add("v2");
dataTable.Columns.Add("v3");
dataTable.Columns.Add("v4");
dataTable.FillDataTable(input);
}
}