Java - 使对象在线程中修改自身
Java - Make an object modify itself in a thread
假设我有很多对象:
public class Main {
public static DB d1 = new DB(1);
public static DB d2 = new DB(2);
public static DB d3 = new DB(3);
public static DB d4 = new DB(4);
我想修改它们。
public static void main(String[] args) {
d1.modifyObject();
d2.modifyObject();
d3.modifyObject();
d4.modifyObject();
}
}
和我希望他们同时修改,因为这需要一些时间。看来我需要多线程。
这是我的 DB
class:
import java.awt.EventQueue;
import java.util.Date;
import java.util.Random;
public class DB {
private int id = 0;
private long field = 0;
public void DB(int id) {
this.id = id;
}
// The contents of this method are not very important.
private void modifyField() {
// [some database interactions which take some seconds to execute]
// for simplicity, emulated with sleep:
long newValue = 0;
try {
newValue = (this.id + new Date().getTime()) % 42;
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
this.field = newValue;
}
public void modifyObject() {
Runnable r = new Runnable(){ @Override public void run() {
this.modifyField(); // THIS DOES NOT WORK OF COURSE, I can't access the objects content from a thread
}};
EventQueue.invokeLater(r);
}
}
我想让Main.d1
、Main.d2
、Main.d3
、Main.d4
等的内容在不耽误主线程的情况下进行更改。我曾经通过在 DB
本身 中访问 Main.d1
来做到这一点。这显然只有在我只有一个对象时才有效。现在,由于我必须处理多个对象,我无法再静态访问 Main
的对象。
我的问题很简单,但恐怕没有简单的答案:我必须将哪些选项 this.modifyField();
放入其自己的线程中?
如何让对象在线程中修改自身?
我认为你完全错了this
。
这里:
Runnable r = new Runnable(){ @Override public void run() {
this.modifyField(); // THIS DOES NOT WORK OF COURSE, I can't access the objects content from a thread
}};
this
指的是new Runnable
。您可以这样访问封闭的 DB
对象:
Runnable r = new Runnable(){ @Override public void run() {
DB.this.modifyField();
}};
此外,如果您使用的是 Java 8,则可以使用方法参考更简洁地编写整个代码:
Runnable r = this::modifyField;
使用 ExecutorServce:
public void foo() throws InterruptedException {
final ExecutorService executorService = newFixedThreadPool(4); //find what works best for you, setting the number of threads as the number of tasks will not be the best solution in all cases
final Future<?> runD1Modify = executorService.submit(getModifyObjectRunnable(d1));
final Future<?> runD2Modify = executorService.submit(getModifyObjectRunnable(d2));
final Future<?> runD3Modify = executorService.submit(getModifyObjectRunnable(d3));
final Future<?> runD4Modify = executorService.submit(getModifyObjectRunnable(d4));
// or in java8
final Future<?> runD1Modify = executorService.submit(() -> d1.modifyField());
final Future<?> runD1Modify = executorService.submit(() -> d2.modifyField());
final Future<?> runD1Modify = executorService.submit(() -> d3.modifyField());
final Future<?> runD1Modify = executorService.submit(() -> d4.modifyField());
}
private Runnable getModifyObjectRunnable(final DB db) {
return new Runnable() {
@Override
public void run() {
db.modifyField();
}
};
}
假设我有很多对象:
public class Main {
public static DB d1 = new DB(1);
public static DB d2 = new DB(2);
public static DB d3 = new DB(3);
public static DB d4 = new DB(4);
我想修改它们。
public static void main(String[] args) {
d1.modifyObject();
d2.modifyObject();
d3.modifyObject();
d4.modifyObject();
}
}
和我希望他们同时修改,因为这需要一些时间。看来我需要多线程。
这是我的 DB
class:
import java.awt.EventQueue;
import java.util.Date;
import java.util.Random;
public class DB {
private int id = 0;
private long field = 0;
public void DB(int id) {
this.id = id;
}
// The contents of this method are not very important.
private void modifyField() {
// [some database interactions which take some seconds to execute]
// for simplicity, emulated with sleep:
long newValue = 0;
try {
newValue = (this.id + new Date().getTime()) % 42;
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
this.field = newValue;
}
public void modifyObject() {
Runnable r = new Runnable(){ @Override public void run() {
this.modifyField(); // THIS DOES NOT WORK OF COURSE, I can't access the objects content from a thread
}};
EventQueue.invokeLater(r);
}
}
我想让Main.d1
、Main.d2
、Main.d3
、Main.d4
等的内容在不耽误主线程的情况下进行更改。我曾经通过在 DB
本身 中访问 Main.d1
来做到这一点。这显然只有在我只有一个对象时才有效。现在,由于我必须处理多个对象,我无法再静态访问 Main
的对象。
我的问题很简单,但恐怕没有简单的答案:我必须将哪些选项 this.modifyField();
放入其自己的线程中?
如何让对象在线程中修改自身?
我认为你完全错了this
。
这里:
Runnable r = new Runnable(){ @Override public void run() {
this.modifyField(); // THIS DOES NOT WORK OF COURSE, I can't access the objects content from a thread
}};
this
指的是new Runnable
。您可以这样访问封闭的 DB
对象:
Runnable r = new Runnable(){ @Override public void run() {
DB.this.modifyField();
}};
此外,如果您使用的是 Java 8,则可以使用方法参考更简洁地编写整个代码:
Runnable r = this::modifyField;
使用 ExecutorServce:
public void foo() throws InterruptedException {
final ExecutorService executorService = newFixedThreadPool(4); //find what works best for you, setting the number of threads as the number of tasks will not be the best solution in all cases
final Future<?> runD1Modify = executorService.submit(getModifyObjectRunnable(d1));
final Future<?> runD2Modify = executorService.submit(getModifyObjectRunnable(d2));
final Future<?> runD3Modify = executorService.submit(getModifyObjectRunnable(d3));
final Future<?> runD4Modify = executorService.submit(getModifyObjectRunnable(d4));
// or in java8
final Future<?> runD1Modify = executorService.submit(() -> d1.modifyField());
final Future<?> runD1Modify = executorService.submit(() -> d2.modifyField());
final Future<?> runD1Modify = executorService.submit(() -> d3.modifyField());
final Future<?> runD1Modify = executorService.submit(() -> d4.modifyField());
}
private Runnable getModifyObjectRunnable(final DB db) {
return new Runnable() {
@Override
public void run() {
db.modifyField();
}
};
}