Java 8 CustomizedThread::new equals new CustomizedThread()? - java

I create Runner in two ways. But ::new doesn't work.
Then I marked the debugger point at Runner1's construct. The debugger point didn't work either.
Who can tell me why?
Is there any difference with Runnable in Runner1::new?
Here is my code.
public static void main(String[] args) {
Runnable n1 = Runner1::new;
Runnable n2 = new Runner2();
ExecutorService executorService = Executors.newFixedThreadPool(2);
executorService.submit(n1);
executorService.submit(n2);
while (true) {
}
}
public static class Runner1 implements Runnable {
public Runner1() {
System.out.println("construct 1");
}
#Override
public void run() {
System.out.println("hello1");
}
}
public static class Runner2 implements Runnable {
public Runner2() {
System.out.println("construct 2");
}
#Override
public void run() {
System.out.println("hello2");
}
}

Runnable n1 = Runner1::new is roughly analogous to this code:
Runnable n1 = () -> new Runner1();
In other words, the Runnable n1 will instantiate a Runner1 when it's called.
That's not what you want to do, instead you want to instantiate a Runner1 and assign that new Runner1 to n1, just as you did with n2.
Using the ::new syntax as a Runnable is not very useful, because a Runnable doesn't have a return value. In other words: your n1 Runnable would instantiate a Runner1 but not make it accessible to any other code.
The way ::new is usually used is to implement something like a Supplier like this:
Supplier<List<Object>> emptyListSuppier = ArrayList::new;

Related

Java Runnable without static reference

I am trying to learn multi-threading using the runnable interface but I am having some trouble figuring out how to pass information. Basically, in the example below, I want to remove the static reference from the Hashmap but if I do that, the program breaks. How do I pass the hashmap to the runnable interface class without using the static keyword?
public class ThreadDemo {
static HashMap <String, Integer>map = new HashMap<>();
public String Hi() {
return "hi";
}
public String Hello() {
return "Hello";
}
public void addToMap(String item) {
if (map.containsKey(item)) {
map.put(item, map.get(item) + 1);
} else {
map.put(item, 1);
}
}
public static void main(String[] args) throws InterruptedException {
ArrayList<Thread> all = new ArrayList<>();
for (int i = 0; i < 50; ++i) {
threader threader = new threader();
all.add(new Thread(threader));
}
for (Thread thread : all) {
thread.start();
}
for (Thread thread : all) {
thread.join();
}
ThreadDemo td = new ThreadDemo();
System.out.println(td.map);
}
}
And a class that implements Runnable
public class threader implements Runnable {
ThreadDemo td = new ThreadDemo();
#Override
public void run() {
synchronized(td.map) {
td.addToMap(td.Hi());
td.addToMap(td.Hello());
}
}
}
A class instance is all about information.
public class threader implements Runnable {
final private ThreadDemo td;
public threader(ThreadDemo td) {
this.td = td;
}
#Override
public void run() {
..
}
}
then to use (details omitted, just the idea):
ThreadDemo theTd = new ThreadDemo();
for (...) {
threader threader = new threader(theTd);
all.add(new Thread(threader));
}
....
Of course, all threads are using the same ThreadDemo, with the same map, so you'll need to ensure access is interlocked in some way, e.g., by using synchronized. The ThreadDemo.addToMap method should be synchronized in this example, rather than the caller of addToMap. This puts the responsibility for the "care of the map" into the place that actually owns the map, and is consequently a better design.
I chose to share the ThreadDemo rather than just the map inside the ThreadDemo, since it looks to me that the intent of ThreadDemo is just to be a wrapper around the map.

Passing command-line arguments to mutliple java threads

I'm trying to create multiple threads in a java program and have them perform arithmetic operations on integers passed as command-line arguments. Obviously neither of the thread classes I'm trying to pass to are in the main method so how can I still access a variable like args[0] from these classes?
public class Mythread {
public static void main(String[] args) {
Runnable r = new multiplication();
Thread t = new Thread(r);
Runnable r2 = new summation();
Thread t2 = new Thread(r2);
t.start();
t2.start();
}
}
class summation implements Runnable{
public void run(){
System.out.print(args[0]);
}
}
class multiplication implements Runnable{
public void run(){
System.out.print(args[1]);
}
}
You should pass in the necessary information in the constructor
class Summation implements Runnable {
private final String info;
public Summation(String info) {
this.info = info;
}
#Override
public void run(){
System.out.print(info);
}
}
Then you can pass in the args values to your threads in main so that you have them in your runnables / threads
public class Mythread {
public static void main(String[] args) {
Runnable r = new multiplication(args[1]);
Thread t = new Thread(r);
Runnable r2 = new summation(args[0]);
Thread t2 = new Thread(r2);
t.start();
t2.start();
}
}

How to determine whether java class is anonymous?

I have such code:
package x.y.z;
public class Test
{
private static class MyRunnable implements Runnable
{
#Override
public void run()
{
System.out.println("World");
}
}
public static void main(String[] args)
{
final Runnable r1 = new Runnable() {
#Override
public void run()
{
System.out.println("Hello");
}
};
final Runnable r2 = new MyRunnable();
r1.run();
r2.run();
}
}
I am working on some code analysis module, and I want to prove that r1 is an anonymous class instance and r2 is not. Both of them are valid objects having the same base class or an interface. How can I do this?
Refinement: All classes are being loaded, so I do not need to analyze the text.
There's the isAnonymousClass method on Class, so:
if (r1.getClass().isAnonymousClass()) {
// ...

How to create a new thread per an existing method (like C#/NET)?

How can I do this in java without using the Runnable class or implementing my threaded code in a run() method?
public void dud()
{
System.out.println("create me on a new thread");
}
public void main()
{
Thread t1 = new Thread(dud).start();
Thread t2 = new Thread(dud).start();
}
Since Java 8, you can use a Lambda:
public void main ()
{
// direct way
new Thread(() -> dud()).start();
// indirect way
Thread t = new Thread(() -> dud());
t.start();
}
Before Java 8, on Java 7, you need to use an anonymus inner class:
public void main ()
{
// direct way
new Thread(new Runnable() { public void run() { dud(); } }).start();
// indirect way
Thread t = new Thread(new Runnable() { public void run () { dud(); } });
t.start();
}
I think you might be able to do it implicitly if you take advantage of Java 8 features :
public class ThreadTest
{
public static void dud()
{
System.out.println("create me on a new thread");
}
public static void main(String[] args)
{
Thread t1 = new Thread(()->dud()).start();
// it might even work with a method reference :
Thread t2 = new Thread(ThreadTest::dud).start();
}
}
You are basically declaring a Runnable implicitly with a lambda expression.
Of course you'll need to either change dud() to be static or create an instance before invoking it.

Passing an argument to a method defined inside a method in Java

So the situation is something like this:
private void myMethod()
{
System.out.println("Hello World"); //some code
System.out.println("Some Other Stuff");
System.out.println("Hello World"); //the same code.
}
We don't want to be repeating our code.
The technique described here works pretty well:
private void myMethod()
{
final Runnable innerMethod = new Runnable()
{
public void run()
{
System.out.println("Hello World");
}
};
innerMethod.run();
System.out.println("Some other stuff");
innerMethod.run();
}
But what if I want to pass in a parameter to that inner method?
eg.
private void myMethod()
{
final Runnable innerMethod = new Runnable()
{
public void run(int value)
{
System.out.println("Hello World" + Integer.toString(value));
}
};
innerMethod.run(1);
System.out.println("Some other stuff");
innerMethod.run(2);
}
gives me: The type new Runnable(){} must implement the inherited abstract method Runnable.run()
While
private void myMethod()
{
final Runnable innerMethod = new Runnable()
{
public void run()
{
//do nothing
}
public void run(int value)
{
System.out.println("Hello World" + Integer.toString(value));
}
};
innerMethod.run(1);
System.out.println("Some other stuff");
innerMethod.run(2);
}
gives me The method run() in the type Runnable is not applicable for the arguments (int).
Nope, that isn't a method but an anonymous object. You can create an extra method to use for the object.
Thread thread = new Thread( new Runnable()
{
int i,j;
public void init(int i, int j)
{
this.i = i;
this.j=j;
}
});
thread.init(2,3);
thread.start();
And wrap runnable in a Thread, and call start! Not run().
Because you can't call the constructor of an anonymous class, as pointed out by #HoverCraft you could extend a named class that implements Runnable.
public class SomeClass implements Runnable
{
public SomeClass(int i){ }
}
Looks like you just want inner methods. Java does't let you have them, so the Runnable hack you describe lets you sort-of declare an inner method.
But since you want more control over it, why not define your own:
interface Inner<A, B> {
public B apply(A a);
}
Then you can say:
private void myMethod(..){
final Inner<Integer, Integer> inner = new Inner<Integer, Integer>() {
public Integer apply(Integer i) {
// whatever you want
}
};
// then go:
inner.apply(1);
inner.apply(2);
}
Or use some library that provides functor objects. There should be many. Apache Commons has a Functor that you can use.

Categories

Resources