Im working on a project and is confused at why the thread wont start when I call .start()
int count = 0;
while (count < urls.length) {
try {
Thread thread = new Thread(new read(urls[count]));
thread.start();
} catch (Exception e) {
}
count++;
}
but if I add
public void start() {
run();
}
in the read class and change the code to
int count = 0;
while (count < urls.length) {
try {
read thread = new read(urls[count]);
thread.start();
} catch (Exception e) {
}
count++;
}
it works fine.
EDIT : here is my read class code
its reading data from url and calling some other methods i have in the class to store data etc.
public class read implements Runnable {
URL url;
public read(String str) throws IOException {
url = new URL(str);
}
public void run() {
try {
URLConnection connect = url.openConnection();
BufferedReader reader = new BufferedReader(new InputStreamReader(connect.getInputStream()));
String input;
String[] temp;
int x = 0;
while (x < 10) {
reader.readLine();
x++;
}
while ((input = reader.readLine()) != null) {
temp = input.split(" ");
temp[2].replaceAll("<br>", "");
String name = temp[0];
int flightNum = Integer.parseInt(temp[1]);
String des = temp[2];
if (Airport.containsKey(flightNum) != true) {
addFlight(flightNum, des);
addPassengerReservation(flightNum, name);
}
else {
addPassengerReservation(flightNum, name);
}
}
reader.close();
}catch (Exception e) {}
}
}
You should make a class implementing Runnable (ClassA), and override the
public void run()
method. From your "main" program, you should call:
Thread th = new Thread(new ClassA());
th.start();
You should never override the start method, or call th.run(). Calling the start method will do some "behind the scenes" work, then call your Runnable Object's run() method for you.
Thread.start() code registers the Thread with scheduler and the scheduler calls the run() method.You need to override the run() method.No need to call run() implicitly.
Related
Is it possible to read a text file by running several threads, so that received line contains information about the thread that read this line?
For now, i can read with one thread:
public class Test {
public static void main(String[] args) throws InterruptedException {
Deque<String> deque = new LinkedList<>();
for (int i = 0; i < 4; i++) {
new Thread(new SubReadThread(deque)).start();
}
new Thread(new WriteThread(deque)).start();
}
}
class SubReadThread implements Runnable {
private final Deque<String> deque;
public SubReadThread(Deque<String> deque) {
this.deque = deque;
}
#Override
public void run() {
try {
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("list.txt"), "UTF8"));
String line = null;
String newLine;
while (true) {
synchronized (deque) {
if (deque.size() < 1) {
line = br.readLine();
newLine = "#" + (Thread.currentThread().getId() - 9) + " " + line;
deque.addLast(newLine);
deque.notify();
} else {
deque.wait();
}
if (line == null) {
break;
}
}
}
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
}
}
class WriteThread implements Runnable {
private final Deque<String> deque;
private List<String> list = new ArrayList<>();
public WriteThread(Deque<String> deque) {
this.deque = deque;
}
#Override
public void run() {
String line;
while (true) {
synchronized (deque) {
if (deque.size() > 0) {
if ((line = deque.pollFirst()).contains("null")) {
break;
} else {
list.add(line);
deque.notifyAll();
}
} else {
try {
deque.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
for(String s : list) {
System.out.println(s);
}
}
}
And expected output something like this:
#3 line1
#1 line2
#4 line3
#2 line4
...............
UPDATE All that was needed to work properly, move BufferedReader to main method and pass its object to the constructor.
I am trying to create a program that will carry on running automatically without me having to do anything. I am a bit confused on how to implement runnable in java so I can create a thread that will go to sleep for a certain period of time and then run the re-run the program after the sleep period is over.
public class work {
public static void main(String[] args) throws IOException, InterruptedException {
work test = new work();
test.information();
}
private ConfigurationBuilder OAuthBuilder() {
ConfigurationBuilder cb = new ConfigurationBuilder();
cb.setOAuthConsumerKey("dy1Vcv3iGYTqFif6m4oYpGBhq");
cb.setOAuthConsumerSecret("wKKJ1XOPZbxX0hywDycDcZf40qxfHvkDXYdINWYXGUH04qU0ha");
cb.setOAuthAccessToken("4850486261-49Eqv5mogjooJr8lm86hB20QRUpxeHq5iIzBLks");
cb.setOAuthAccessTokenSecret("QLeIKTTxJOwpSX4zEasREtGcXcqr0mY8wk5hRZKYrH5pd");
return cb;
}
public void information() throws IOException, InterruptedException {
ConfigurationBuilder cb = OAuthBuilder();
Twitter twitter = new TwitterFactory(cb.build()).getInstance();
try {
User user = twitter.showUser("ec12327");
Query query = new Query("gym fanatic");
query.setCount(100);
query.lang("en");
String rawJSON =null ;
String statusfile = null;
int i=0;
try {
QueryResult result = twitter.search(query);
for(int z = 0;z<5;z++){
for( Status status : result.getTweets()){
System.out.println("#" + status.getUser().getScreenName() + ":" + status.getText());
rawJSON = TwitterObjectFactory.getRawJSON(status);
statusfile = "results" + z +".txt";
storeJSON(rawJSON, statusfile);
i++;
}
}
System.out.println(i);
}
catch(TwitterException e) {
System.out.println("Get timeline: " + e + " Status code: " + e.getStatusCode());
if(e.getErrorCode() == 88){
Thread.sleep(900);
information();
}
}
} catch (TwitterException e) {
if (e.getErrorCode() == 88) {
System.err.println("Rate Limit exceeded!!!!!!");
Thread.sleep(90);
information();
try {
long time = e.getRateLimitStatus().getSecondsUntilReset();
if (time > 0)
Thread.sleep(900000);
information();
} catch (InterruptedException e1) {
e1.printStackTrace();
}
}
}
}
private static void storeJSON(String rawJSON, String fileName) throws IOException {
FileWriter fileWriter = null;
try
{
fileWriter = new FileWriter(fileName, true);
fileWriter.write(rawJSON);
fileWriter.write("\n");
}
catch(IOException ioe)
{
System.err.println("IOException: " + ioe.getMessage());
} finally {
if(fileWriter!=null) {
fileWriter.close();
}
}
}
}
You have severable options to implement a thread in Java.
Implementing Runnable
When a class implements the Runnable interface, he has to override the run() method. This runnable can be passed to the constructor of a Thread. This thread can then be executed using the start() method. If you'd like to have this thread run forever and sleep, you could do something like the following:
public class HelloRunnable implements Runnable {
public void run() {
while(true){
Thread.sleep(1000);
System.out.println("Hello from a thread!");
}
}
public static void main(String args[]) {
(new Thread(new HelloRunnable())).start();
}
}
Extending Thread
Thread itself also has a run() method. When extending thread, you can override the Thread's run() method and provide your own implementation. Then you'd have to instantiate your own custom thread, and start it in the same way. Again, like the previous you could do this:
public class HelloThread extends Thread {
public void run() {
while(true){
Thread.sleep(1000);
System.out.println("Hello from a thread!");
}
}
public static void main(String args[]) {
(new HelloThread()).start();
}
}
Source: Oracle documentation
Building on the previous answer, you need to either extend Thread or implement Runnable on your Work class. Extending Thread is probably easier.
public class work extends Thread {
public void run() {
// your app will run forever, consider a break mechanism
while(true) {
// sleep for a while, otherwise you'll max your CPU
Thread.sleep( 1000 );
this.information();
}
}
public static void main(String[] args) throws IOException, InterruptedException {
work test = new work();
test.start();
}
// ... rest of your class
}
public static void main(String[] args){
Thread thread = new Thread(runnable); // create new thread instance
thread.start(); // start thread
}
public static Runnable runnable = new Runnable(){
#Override
public void run(){
final int DELAY = 500;
while(true){
try{
// Code goes here;
Thread.sleep(DELAY)
} catch(Exception e){
e.printStackTrace();
}
}
}
}
I need to get a String value from a Thread, but I don't get it! Global variables don't work! Can you help me please?
This is my code. I need to use the dataString:
public class Deserializable {
public void execute() {
new Thread() {
public void run() {
String surl = "http://myaddressxxxxx";
HttpURLConnection urlConnection = null;
URL url = null;
try {
url = new URL(surl);
urlConnection = (HttpURLConnection) url.openConnection();
InputStream in = new BufferedInputStream(
urlConnection.getInputStream());
int b = in.read();
List<Byte> bytes = new LinkedList<Byte>();
while (b != -1) {
bytes.add((byte) b);
b = in.read();
}
byte[] array = new byte[bytes.size()];
for (int i = 0; i < bytes.size(); i++) {
array[i] = bytes.get(i).byteValue();
}
// I need return this String.
String dataString = new String(array);
} catch (Exception e) {
e.printStackTrace();
} finally {
urlConnection.disconnect();
}
}
}.start();
}
Thread can be extended to have fields, like for your dataString. These fields can be accessed from the same thread or from a different one, as long they have references to each other.
public class ThreadA extends Thread {
public String dataString;
public void run(){
...
this.dataString = ...;
...
}
}
public class ThreadB extends Thread {
private final ThreadA ta;
public ThreadB(ThreadA ta){
super();
this.ta = ta;
}
public void run(){
...
do something with ta.dataString...
...
}
}
Of course, this poses the problem of concurrent access to the field dataString. Consider using synchronized, if this is an issue in your case. Have a look at this tutorial on concurrency for more information.
I am trying to write a Multithreaded Web Crawler in Java using Jsoup.I have a Java Class "Master" which creates 6 threads(5 for crawling and 1 for maintenance of queues) ,and 3 queues namely "to_do","to_do_next"(to be done in next iteration) and "done"(final links).
I am using sunchronized locks on shared queues.The idea is as soon as all the 5 threads find the "to_do" queue empty they notify a maintenance thread which does some work and notify these threads back.But the problem is the program is getting blocked sometimes (so i assume there is some race condition I am not able to take care of)....also upon checking I found that not all threads are getting notified by maintenace thread.so is it possible that some notify signals might be lost??
Code for Master class
private Queue<String> to_do = new LinkedList<String>();
private Queue<String> done= new LinkedList<String>();
private Queue<String> to_do_next = new LinkedList<String>();
private int level = 1;
private Object lock1 = new Object();
private Object lock2 = new Object();
private Object lock3 = new Object();
private static Thread maintenance;
public static Master mref;
public static Object wait1 = new Object();
public static Object wait2 = new Object();
public static Object wait3 = new Object();
public static int flag = 5;
public static int missedSignals = -1;
public boolean checkToDoEmpty(){
return to_do.isEmpty();
}
public int getLevel() {
return level;
}
public void incLevel() {
this.level++;
}
public static void interrupt() {
maintenance.interrupt();
}
public void transfer() {
to_do = to_do_next;
}
public String accessToDo() {
synchronized(lock1){
String tmp = to_do.peek();
if(tmp != null)
tmp = to_do.remove();
return tmp;
}
}
public void addToDoNext(String url){
synchronized(lock2){
to_do_next.add(url);
}
}
public void addDone(String string) {
synchronized(lock3){
done.add(string);
}
}
public static void main(String[] args){
Master m = new Master();
mref = m;
URL startUrl = null;
try {
startUrl = new URL("http://cse.iitkgp.ac.in");
}catch (MalformedURLException e1) {
e1.printStackTrace();
}
Thread t1 = new Thread(new Worker(1));
Thread t2 = new Thread(new Worker(2));
Thread t3 = new Thread(new Worker(3));
Thread t4 = new Thread(new Worker(4));
Thread t5 = new Thread(new Worker(5));
maintenance = new Thread(new MaintenanceThread());
m.to_do.add(startUrl.toString());
maintenance.start();
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
try {
t1.join();
t2.join();
t3.join();
t4.join();
t5.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
/*for(String s:m.done)
System.out.println(s);
for(String s:m.to_do)
System.out.println(s);*/
}
Code for Worker threads
public void run() {
while(Master.mref.getLevel() != 3){
if(!Master.mref.checkToDoEmpty()){
String url = Master.mref.accessToDo();
if(url != null && url.contains("iitkgp") && url.contains("http://")){
try {
Document doc = Jsoup.connect(url).get();
org.jsoup.select.Elements links = doc.select("a[href]");
for(org.jsoup.nodes.Element l: links){
Master.mref.addToDoNext(l.attr("abs:href").toString());
}
Master.mref.addDone(url);
} catch (IOException e) {
System.out.println(url);
e.printStackTrace();
}
continue;
}
}
//System.out.println("thread " + id + " about to notify on wait1");
synchronized(Master.wait1){
Master.wait1.notify();
Master.missedSignals++;
}
synchronized(Master.wait2){
try {
Master.wait2.wait();
System.out.println("thread " + id + " coming out of wait2");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
System.out.println("Terminating " + id + " thread");
Master.flag--;
if(Master.flag == 0)
Master.interrupt();
}
Code for Maintenace thread
while(Master.flag != 0){
try {
synchronized(Master.wait1){
if(Master.missedSignals != -1){
count += Master.missedSignals;
Master.missedSignals = -1;
}
while(count != 5){
Master.wait1.wait();
if(Master.missedSignals != -1)
count += Master.missedSignals;
Master.missedSignals = -1;
count++;
}
count = 0;
}
//System.out.println("in between");
Master.mref.incLevel();
Master.mref.transfer();
synchronized(Master.wait2){
Master.wait2.notifyAll();
}
} catch (InterruptedException e) {
break;
}
}
System.out.println("Mainta thread gone");
Your design is way too complicated
i suggest using for your to_do queue the following: LinkedBlockingQueue
This is a blocking queue, which means that your threads will ask for an object from the queue and only when one will appear they will get the object, till then they will stay blocking.
Just use the following methods to put and take objects in the queue: put() & take()
Please look at the following two links for more explanations on this special queue:
http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/LinkedBlockingQueue.html
http://tutorials.jenkov.com/java-util-concurrent/linkedblockingqueue.html
Now, your only concern is killing the threads when they are finished with their work, for that I suggest the following:
boolean someThreadStillAlive = true;
while (someThreadStillAlive) {
someThreadStillAlive = false;
Thread.sleep(200);
for (Thread t : fetchAndParseThreads) {
someThreadStillAlive = someThreadStillAlive || t.isAlive();
}
}
This will occur in your main code block, where it will loop & sleep till all threads are finished.
Ohh, instead of take(), you can use poll(int timeout...) where it will wait for the timeout to finish and if no new object is inserted into the queue it will kill the thread.
All of the above, were used successfully in my own crawler.
I would like to know how to access the Service and Domains properly in this sample class placed in src/java folder
public class NewsIngestion implements Runnable {
private String str;
private int num;
private Logger log = Logger.getLogger("grails.app");
private static boolean isRunning;
private Thread t;
private WorkerJobService jobService;
private NewsService newsService;
public NewsIngestion(String s, int n)
{
jobService = new WorkerJobService();
newsService = new NewsService();
str = s;
num = n;
isRunning = false;
t = new Thread (this, "NewsIngestion");
}
public void run ()
{
while(isRunning){
try{
if(jobService.isJobEnabled("ConsumeFeedsJob") && jobService.lockJob("ConsumeFeedsJob")){
log.info("${this.class.name}: ConsumeFeedsJob started");
try{
// get all sources
List sources = (List) InvokerHelper.invokeMethod(RSSFeed.class, "list", null);
for(int i = 0; i < sources.size(); i++) {
RSSFeed s = (RSSFeed) sources.get(i);
// check if it's time to read the source
int diff = DateTimeUtil.getSecondsDateDiff(s.getLastChecked(), new Date());
if(s.getLastChecked() == null || diff >= s.getCheckInterval()){
List keyword_list = (List) InvokerHelper.invokeMethod(Keyword.class, "list", null);
for(int j = 0; j < keyword_list.size(); j++) {
String keyword = (String) keyword_list.get(j);
try{
newsService.ingestNewsFromSources(keyword, s);
}catch(Exception e){
log.error("${this.class.name}: ${e}");
}
log.debug("Completed reading feeds for ${keyword}.");
log.info("${this.class.name}: Reading feeds for '${keyword}' (${s.feedName}) took ${Float.toString(st2.getDuration())} second(s).");
}
s.setLastChecked(new Date());
InvokerHelper.invokeMethod(RSSFeed.class, "save", null);
}
log.info("${this.class.name}: Reading feeds for '${s.feedName}' for all keywords took ${Float.toString(st.getDuration())} second(s).");
}
}catch(Exception e){
log.error("${this.class.name}: Exception: ${e}");
}
log.info("${this.class.name}: ConsumeFeedsJob ended.");
// unlock job
jobService.unlockJob("ConsumeFeedsJob");
}
log.info("alfred: success");
}
catch (Exception e){
log.info("alfred exception: " + e.getMessage());
}
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
log.info(e.getMessage());
}
}
}
public void start() {
if(t == null){
t = new Thread (this, "NewsIngestion");
}
if(!isRunning){
isRunning = true;
t.start();
}
}
public void stop() {
isRunning = false;
}
public boolean isRunning() {
return isRunning;
}
}
I'm encountering this error message:
No Hibernate Session bound to thread,
and configuration does not allow
creation of non-transactional one here
Thanks.
You shouldn't instantiate the service class by yourself, but instead take the class instance from the main context
import org.codehaus.groovy.grails.commons.ApplicationHolder
def ctx = ApplicationHolder.application.mainContext
def newsService = ctx.newsService
If you're using Java
import org.codehaus.groovy.grails.commons.ApplicationHolder
public class SomeClass {
SomeService someService;
public SomeClass() {
someService = (SomeService) ApplicationHolder.getApplication().getMainContext().getBean("someService");
}
}
Consider using Spring and #Transactional annotation or AOP.