每次我必须创建可变数量的线程。 我这样做是通过创建一个Threads数组并创建多个线程。
但是,我不明白如何启动这些n个线程表现得像多线程概念。 我希望它们并行运行。
请指导在这个场所做什么。
答案 0 :(得分:37)
但是,我不明白如何启动这些n个线程表现得像多线程概念。我希望它们并行运行。
您当然可以使用循环创建一个线程数组:
Thread[] threads = new Thread[NUM_JOBS_TO_CREATE];
for (int i = 0; i < threads.length; i++) {
threads[i] = new Thread(new Runnable() {
public void run() {
// some code to run in parallel
// this could also be another class that implements Runnable
}
});
threads[i].start();
}
这将导致线程在后台并行运行。然后,您可以稍后与他们一起等待他们全部完成,然后再继续。
// wait for the threads running in the background to finish
for (Thread thread : threads) {
thread.join();
}
但我不建议自己管理线程,而是建议使用内置Java Executors
。他们为您做的所有这些都更容易管理。此方法的一个好处是它将任务与运行它们的线程分开。例如,您可以启动10个线程来并行运行1000和1000个任务。
以下是一些示例ExecutorService
代码:
// create a pool of threads, 10 max jobs will execute in parallel
ExecutorService threadPool = Executors.newFixedThreadPool(10);
// submit jobs to be executing by the pool
for (int i = 0; i < NUM_JOBS_TO_CREATE; i++) {
threadPool.submit(new Runnable() {
public void run() {
// some code to run in parallel
// this could also be another class that implements Runnable
}
});
}
// once you've submitted your last job to the service it should be shut down
threadPool.shutdown();
// wait for the threads to finish if necessary
threadPool.awaitTermination(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
有关详细信息,请参阅Java tutorial on the thread executors。
答案 1 :(得分:3)
非常努力地不创建线程数组并尝试管理它们 - 它很快就会陷入困境。如果需要一个线程池来运行任务,则需要一个生产者 - 消费者队列。创建一个并将它(或者包含它作为成员的线程池对象实例)传递给创建它们的线程。线程循环,获取任务并执行它们。
执行此操作的简单方法是使用@Gray详细说明的ExecutorService,(+ 1)。
为了强调,我再说一遍,不要试图对数组,列表或向量中的线程进行微观管理,启动它们,在“boss / management”循环中检查它们的状态,终止/中止它们,销毁它们等等。它就像一辆保时捷911--在花费了大量金钱/时间来获得一辆保时捷911之后,你会得到一些似乎工作正常的东西然后会突然断裂并将你旋转到一棵树上。
为长时间阻止的作业使用专用线程,为可以集中且快速完成的作业使用线程池。
答案 2 :(得分:2)
基本伪代码:
create x threads, store them in an array or list;
for each thread in the list/array
call start() on the thread object;
答案 3 :(得分:0)
在需要多线程的类中,我设置在类的顶部:
private static final ExecutorService executor = Executors.newCachedThreadPool();
&安培;在Java 8+中使用lamda表达式,无论我需要在新线程中运行的东西:
executor.submit(() -> {
myOtherClass.myFunction(doSomething);
});
使用newCachedThreadPool
Java将根据系统上的cpu核心数管理线程总数。在一段时间不活动后自动停止它们(默认为60
秒)。
答案 4 :(得分:0)
from tkinter import ttk
from tkinter import *
import tkinter
import sqlite3
class cadastro:
# connection dir property----------------------------------------------------
# propriedade do dir de conexão------------------------------------------------
db_name = 'database.db'
def __init__(self, window):
# Initializations ----------------------------------------------
#Inicializações --------------------------------------------------
self.wind = window
self.wind.title('cadastro DataSet')
# Creating a Frame Container ------------------------------------------------
#Criando um Contêiner de Quadro-------------------------------------------
frame = LabelFrame(self.wind, text = 'Registrar novo cadastro')
frame.grid(row = 0, column = 0, columnspan = 3, pady = 20)
# Name Input------------------------------------------------------
Label(frame, text = 'Name: ').grid(row = 1, column = 0)
self.name = Text(frame, width=20,height=3)
self.name.config(font=("consolas", 12), undo=True, wrap='word')
self.name.focus()
self.name.grid(row = 1, column = 1)
self.scrollb = Scrollbar(frame, command=self.name.yview)
self.scrollb.grid(row=1, column=1, sticky='ns', columnspan=3)
self.name['yscrollcommand'] = self.scrollb.set
Label(frame, text = 'Description: ').grid(row = 2, column = 0)
self.description = Text(frame, width=20,height=3)
self.description.config(font=("consolas", 12), undo=True, wrap='word')
self.description.focus()
self.description.grid(row = 2, column = 1)
self.scrollb = Scrollbar(frame, command=self.description.yview)
self.scrollb.grid(row=2, column=1, sticky='ns', columnspan=3)
self.description['yscrollcommand'] = self.scrollb.set
Label(frame, text = 'Local: ').grid(row = 3, column = 0)
self.local = Text(frame,width=20,height=3)
self.local.config(font=("consolas", 12), undo=True, wrap='word')
self.local.focus()
self.local.grid(row = 3, column = 1)
self.scrollb = Scrollbar(frame, command=self.local.yview)
self.scrollb.grid(row=3, column=1, sticky='ns', columnspan=3)
self.local['yscrollcommand'] = self.scrollb.set
self.tree = ttk.Treeview(frame,columns=("Name", "Description"))
self.tree.heading("#0", text="Name", anchor= CENTER)
self.tree.heading("#1", text="Description", anchor= CENTER)
self.tree.heading("#2", text="Local", anchor= CENTER)
self.tree.grid(row = 4, column = 0, columnspan = 5, ipady=10)
self.scrollb = Scrollbar(frame, command=self.tree.yview)
self.scrollb.grid(row=4, column=5, sticky='ns', rowspan=1)
self.tree['yscrollcommand'] = self.scrollb.set
# Button Add cadastro --------------------------------------------------
ttk.Button(frame, text = 'Inserir', command = self.add_cadastro).grid(row = 5, column = 1, sticky = W + E)
#Botão para excluir cadastro--------------------------------------------
ttk.Button(frame, text = 'DELETE', command = self.delete_cadastro).grid(row = 5, column = 2, sticky = W + E)
#Botão para atualizar cadastro------------------------------------------
ttk.Button(frame, text = 'EDIT', command = self.edit_cadastro).grid(row = 5, column = 3, sticky = W + E)
# Output Messages ------------------------------------------------------
# Mensagens de Saída ---------------------------------------------------
self.message = Label(text = '', fg = 'red')
self.message.grid(row = 7, column = 0, columnspan = 3, sticky = W + E)
# Filling the Rows-------------------------------------------------------
# Preenchendo as filas----------------------------------------------------
self.get_cadastro()
# Function to Execute Database Querys----------------------------------------------
# Função para executar bancos de dados --------------------------------------------
def run_query(self, query, parameters = ()):
with sqlite3.connect(self.db_name) as conn:
cursor = conn.cursor()
cursor.execute("CREATE TABLE IF NOT EXISTS cadastro (id INTEGER PRIMARY KEY , name TEXT, description TEXT, local TEXT)")
result = cursor.execute(query, parameters)
conn.commit()
return result
def get_cadastro(self):
# cleaning Table ----------------------------------------------------------------
# mesa de limpeza------------------------------------------------------------------
records = self.tree.get_children()
for element in records:
self.tree.delete(element)
query = 'SELECT * FROM cadastro ORDER BY name DESC'
db_rows = self.run_query(query)
for row in db_rows:
self.tree.insert('', 0, text = row[1], values = (row[2],row[3]))
# Validação De Entrada De Usuário -----------------------------------------------------
def validation(self):
return (self.name.get(1.0, END)),(self.description.get(1.0, END), (self.local.get(1.0, END)))
def add_cadastro(self):
if self.validation():
query = 'INSERT INTO cadastro VALUES(NULL, ?, ?, ?)'
parameters = (self.name.get(1.0, END), self.description.get(1.0, END), self.local.get(1.0, END))
self.run_query(query, parameters)
self.message['text'] = 'cadastro {} added Successfully'.format(self.name.get(1.0, END))
self.name.delete(1.0, END)
self.description.delete(1.0, END)
self.local.delete(1.0, END)
else:
self.message['text'] = 'Name and Data is Required'
self.get_cadastro()
def delete_cadastro(self):
self.message['text'] = ''
try:
self.tree.item(self.tree.selection())['text'][0]
except IndexError as e:
self.message['text'] = 'Please select a Record'
return
self.message['text'] = ''
name = self.tree.item(self.tree.selection())['text']
query = 'DELETE FROM cadastro WHERE name = ?'
self.run_query(query, (name, ))
self.message['text'] = 'Record {} deleted Successfully'.format(name)
self.get_cadastro()
def edit_cadastro(self):
self.message['text'] = ''
try:
self.tree.item(self.tree.selection())['values'][0]
except IndexError as e:
self.message['text'] = 'Please, select Record'
return
name = self.tree.item(self.tree.selection())['text']
description = self.tree.item(self.tree.selection())['values'][0]
local = self.tree.item(self.tree.selection())['values'][1]
self.edit_wind = Toplevel()
self.edit_wind.title = 'Edit Civilization'
frame2 = LabelFrame(self.edit_wind, text = 'Registros atuais,janela de visualização avançada.')
frame2.grid(row = 0, column = 0, columnspan = 3, pady = 20)
self.nomelab = Label(frame2, text = 'Name: ').grid(row = 1, column = 0)
message2 = Text(frame2, height=5, width=50)
message2.config(font=("consolas", 12), undo=True, wrap='word')
message2.insert(END, name)
message2.grid(row = 2, column = 0, columnspan = 2, sticky = W + E)
self.descriptlab = Label(frame2, text = 'Description: ').grid(row = 3, column = 0)
message3 = Text(frame2, height=5, width=34)
message3.config(font=("consolas", 12), undo=True, wrap='word')
message3.insert(END, description)
message3.grid(row = 4, column = 0, columnspan = 2, sticky = W + E)
self.locallab = Label(frame2, text = 'Local: ').grid(row = 5, column = 0)
message4 = Text(frame2, height=5, width=34)
message4.config(font=("consolas", 12), undo=True, wrap='word')
message4.insert(END, local)
message4.grid(row = 6, column = 0, columnspan = 2, sticky = W + E)
ttk.Button(
frame2, text = 'Update',
command = lambda: self.update_castro(name, message2, message3, message4)
).grid(row = 7, column = 3, sticky = W + E)
def update_castro(self, old_name, message2, message3, message4):
message2 = message2.get(1.0, END)
message3 = message3.get(1.0, END)
message4 = message4.get(1.0, END)
query = 'UPDATE cadastro set name = ?, description = ?, local = ? WHERE name = ?'
self.run_query(query, (message2, message3, message4, old_name ))
self.get_cadastro()
self.edit_wind.destroy()
if __name__ == '__main__':
window = Tk()
application = cadastro(window)
window.mainloop()