NetBeans, многопоточное программирование, проблемы с отображением дочерних фреймов

 
 
 
Сообщения:1
Здравствуйте! Я пытаюсь разобраться с многопоточным программированием на Java, NetBeans. Есть задание:

Написать приложение, содержащее не менее двух тредов. Каждый из этих тредов должен искать файлы по заданному шаблону и каждый из них должен выводить результат в свое собственное окно.

С этой целью я создала свой класс MyThread, в котором для каждого нового потока создаю свой Frame, где отображаю полученный список файлов. Но вот проблема: не работает созданная мною возможность приостановить/запустить вновь поток. Когда я запускаю приложение, то вижу пустые фреймы, их содержимое отображается только после завершения работы потока. Причем, это происходит только в случае, если я пытаюсь как-то работать с побочными потоками. (В главном потоке я использую цикл while, который выводит в заголовок главного фрейма количество активных потоков. Или, например, использую метод join(), чтобы главный поток дождался окончания побочных.) Если же я просто запускаю потоки и после start() больше с ними не работаю, то все работает правильно. (Кстати говоря, я пыталась проделать то же самое, создавая вместо новых фреймов новые окна, написав свой класс, наследующий JDialog. Проблема осталавалась та же :( )

Я пытаюсь понять причину проблемы уже не первую неделю, поэтому буду очень благодарна любой помощи! :)

Вот сам класс для побочного потока:
class MyThread extends Thread
{
	public static File myDir;
        public static boolean dirFlag = true;
	    public static String pattern;
        public static String strPattern;
        public int step = 0;
        private boolean play = true;
        private Form threadForm;
        
        MyThread(String arg1, int arg2) {
                super(arg1);
                step = arg2;
                MainForm.kol++;
	}
        
	public synchronized void fileSearch(File myDir, List<File> list) throws InterruptedException {
                
                while (!play)
                    wait();
                
		if (!myDir.canRead() || !myDir.canExecute()) 
                        return;
		File[] myDirContent = myDir.listFiles();
		if (myDirContent == null || myDirContent.length == 0)
                        return;
		for (File entry: myDirContent) {
                    if (entry.isDirectory() && dirFlag) {
                        fileSearch(entry, list);
                            continue;
                    }
                    if (fileCheckPattern(entry, pattern))
                        list.add(entry);
		}
	}
        
        public synchronized static void fileSearchAndStr(File myDir, List<File> list) throws FileNotFoundException {
		
                while (!play)
                   wait();
                
                if (!myDir.canRead() || !myDir.canExecute())
                    return;
		File[] myDirContent = myDir.listFiles();
		if (myDirContent == null || myDirContent.length == 0)
			return;
		for (File entry: myDirContent) {
                    if (entry.isDirectory() && dirFlag) {
                        fileSearchAndStr(entry, list);
                        continue;
                    }
                    if (fileCheckPattern(entry, pattern) && (fileCheckStr(entry, strPattern)))
                        list.add(entry);
		}  
	}
	
	public static boolean fileCheckPattern(File f, String pattern){
            
                if (f.getName().matches(pattern))
                    return true;
		return false;
	}
	
	public static boolean fileCheckStr(File f, String str) throws FileNotFoundException {
            
		if (!f.isFile() || !f.canRead() || !f.canExecute())
			return false;
		if (f.length() == 0)
			return false;
		Scanner input = new Scanner(new FileInputStream(f));
		while (input.hasNextLine()) {
                    String s = input.nextLine();
                    if (s.equals(str)) {
                            input.close();
                            return true;
                    }
		}
			input.close();
		return false;
	}
        
        public synchronized void play() {
            play = true;
            notify();
            threadForm.setText("\nПоток \"" + getName() + "\" возобновлен.");
        }

        public void pause() {
           play = false;
           threadForm.setText("\nПоток \"" + getName() + "\" приостановлен.");
        }
	
	public void run() {
            
                threadForm = new Form();
                threadForm.setVisible(true);
                threadForm.setText("Поток \"" + getName() + "\" начинает свою работу...");
                
                List<File> list = new ArrayList<>();
                
		try {
                        if (strPattern == null || strPattern.isEmpty())
                                fileSearch(myDir, list);
                        else
                                fileSearchAndStr(myDir, list);
                        threadForm.setList(list);
                        //tDialog.setList(list);
                  
                } catch (InterruptedException ex) {
                    interrupt();
                    play = true;
                    threadForm.setText("\nПоток \"" + getName() + "\" был прерван!");
                } catch (Exception e) {
                    
                        String s = "\nВозникла ошибка в работе потока!";
                        if (e.getMessage() != null)
                            s += "\n" + e.getMessage();
                        threadForm.setText(s);
                }
                
                threadForm.setText("\n\nПоток \"" + getName() + "\" завершил свою работу.");
                threadForm.setSuspendF();
                MainForm.kol--;
	}
}


Это класс создаваемого дочернего фрейма:
public class Form extends javax.swing.JFrame {

    private MyThread t = (MyThread)Thread.currentThread();
    
    public Form() {
        initComponents();
        setTitle("Thread \"" + t.getName() + "\"");
        setLocation(t.step);
    }
    
    public void setLocation(int koef)
    {
        koef = ((koef % 2) == 0) ? 0 : 1;
        setLocation(200 + 550*koef, 150);
    }
    
    public void setText(String text)
    {
        if (text != null && !text.isEmpty())
            jTextArea1.append(text);
    }
    
    public void setList(List<File> list)
    {
        jTextArea1.append("\n\nРезультат работы потока \"" + t.getName() + "\":");
        if (!list.isEmpty())
        {
            for (File entry: list)
                jTextArea1.append("\n" + entry.getAbsolutePath());
        }
        else
            jTextArea1.append("\nНе найдено файлов, удовлетворяющих шаблону.");
    }
    
    public void setSuspendF()
    {
        jButton1.setEnabled(false);
    }    

    private void jButton3ActionPerformed(java.awt.event.ActionEvent evt) {                                         
        setVisible(false);
        t.interrupt();
    }                                        

    private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {                                         
            checkThread();
    }                                        

    private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {                                         
            checkThread();
    }                                        

    private void formWindowClosing(java.awt.event.WindowEvent evt) {                                   
       t.interrupt();
    }                                  

    public void checkThread() {
        
        if (t.getState() == Thread.State.TERMINATED)
            JOptionPane.showMessageDialog(null, "Поток уже закончил работу!", "Error!", JOptionPane.ERROR_MESSAGE);
        else {
            if (t.getState() != Thread.State.WAITING && jButton1.isEnabled()) {
                t.pause();
                jButton1.setEnabled(false);
                jButton2.setEnabled(true);
            }
            else {
                t.play();
                jButton1.setEnabled(true);
                jButton2.setEnabled(false);
            }
        }
    }


А это, собственно, использование:
public class MainForm extends JFrame { 
          private MyThread[] threads;
          public static int kol = 0;
          private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {                                         

                 try {
                        threads = new MyThread[2];
                        threads[0] = new MyThread("One", 0);
                        threads[1] = new MyThread("Two", 1);

                        for (MyThread t: threads)
                           t.setPriority(Thread.MAX_PRIORITY);
                        Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
                        
                        for (MyThread t: threads)
                            t.start();
                        
                        int a = MainForm.kol;
                        while (a != 0)
                        {
                            a = MainForm.kol;
                            setTitle("Active threads: " + a);
                           // Thread.sleep(300);
                        }
                        
                } catch (Exception e) {
                     JOptionPane.showMessageDialog(null, "Возникла ошибка!\n" + ((e.getMessage() != null) ? e.getMessage() : "") , "Error!", JOptionPane.ERROR_MESSAGE);
                }
         }
}
 
 
Сообщения:284
Для понимания того, как работать с фоновыми потоками, которые пытаются обновить GUI можно почитать вот эти статьи: один, два.
 
 
Сообщения:314
Alinka:
Проблема осталавалась та же :( )

разделяй и властвуй.. попробуй все сделать иначе..
например, так
package file.search;

public interface SearchControl {
	void stopWork();

	void continueWork();
}


package file.search;

import javax.swing.*;

public class Main {
	public static void main(String[] args) {
		SwingUtilities.invokeLater(new MainUI());
	}
}


package file.search;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.io.File;

public class MainUI extends JFrame implements Runnable {

	private final JFrame frame;

	public MainUI() {
		Dimension size = new Dimension(500, 300);
		frame = new JFrame();
		frame.setSize(size);
		frame.setMinimumSize(size);

		JPanel panel = new JPanel();
		panel.setLayout(new BorderLayout());
		frame.setContentPane(panel);

		JPanel topPanel = new JPanel();
		topPanel.setLayout(new FlowLayout());
		panel.add(topPanel, BorderLayout.NORTH);

		final JPanel center = new JPanel();
		center.setLayout(new FlowLayout());
		panel.add(center, BorderLayout.CENTER);
		center.setSize(new Dimension(400, 300));

		final JTextField pathField = new JTextField("", 20);
		final JTextField maskField = new JTextField("", 5);
		topPanel.add(pathField);
		topPanel.add(maskField);

		JButton search = new JButton("Search");
		search.addActionListener(new AbstractAction() {
			@Override
			public void actionPerformed(ActionEvent e) {
				String path = pathField.getText().trim();
				String text = maskField.getText().trim();
				if (path.isEmpty() || text.isEmpty()) {
					return;
				}
				Result result = new Result(new File(path), text);
				SwingUtilities.invokeLater(result);
				SwingUtilities.invokeLater(new Runnable() {
					@Override
					public void run() {
						center.add(new MyButton(result));
						SwingUtilities.updateComponentTreeUI(frame);
					}
				});
			}
		});
		topPanel.add(search);
	}

	@Override
	public void run() {
		frame.setVisible(true);
	}
}


package file.search;

import javax.swing.*;
import java.awt.event.ActionEvent;

class MyButton extends JButton {
	private boolean doWork = true;

	public MyButton(final Result result) {
		setText("mask: " + result.getMask());

		addActionListener(new AbstractAction() {
			@Override
			public void actionPerformed(ActionEvent e) {
				if (doWork) {
					result.stopWork();
				} else {
					result.continueWork();
				}
				doWork = !doWork;
			}
		});
	}
}


package file.search;

import java.io.File;
import java.util.ArrayList;

public interface UpdateResult {
	void update(ArrayList<File> files);
}


package file.search;

import javax.swing.*;
import java.awt.*;
import java.io.File;
import java.util.ArrayList;
import java.util.Random;

public class Result extends JFrame implements Runnable, SearchControl, UpdateResult {

	private final JFrame frame;
	private final JLabel result;
	private final String mask;
	private final File path;
	private Search search;

	public Result(File path, String mask) {
		this.path = path;
		this.mask = mask;
		Dimension size = new Dimension(400, 300);
		frame = new JFrame();
		frame.setSize(size);
		frame.setMinimumSize(size);
		Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
		Random random = new Random();
		frame.setLocation(new Point(random.nextInt((int) screenSize.getWidth()),
		                            random.nextInt((int) screenSize.getHeight())));
		JPanel panel = new JPanel();
		panel.setLayout(new FlowLayout());
		frame.setContentPane(panel);
		frame.setTitle(mask);
		result = new JLabel("<empty>");
		panel.add(result);
	}

	@Override
	public void run() {
		frame.setVisible(true);
		search = new Search(this, path, mask);
		search.start();
	}

	public String getMask() {
		return mask;
	}

	@Override
	public void stopWork() {
		search.stopWork();
	}

	@Override
	public void continueWork() {
		search.continueWork();
	}

	@Override
	public void update(final ArrayList<File> files) {
		SwingUtilities.invokeLater(new Runnable() {
			@Override
			public void run() {
				StringBuilder sb = new StringBuilder();
				for (File file : files) {
					sb.append(sb.length() > 0 ? "\n" : "").append(file.getAbsolutePath());
				}
				result.setText(sb.toString());
			}
		});
	}
}



package file.search;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Scanner;

class Search extends Thread implements SearchControl {
	private final File         path;
	private final String       mask;
	private final UpdateResult result;
	private       boolean      doWork;

	public Search(UpdateResult result, File path, String mask) {
		this.result = result;
		this.path = path;
		this.mask = mask;
		doWork = true;
	}

	public void run() {
		ArrayList<File> list = new ArrayList<>();
		try {
			if (mask == null || mask.isEmpty()) {
				fileSearch(path, list);
			} else {
				fileSearchAndStr(path, list);
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			result.update(list);
		}
	}

	@Override
	public void stopWork() {
		doWork = false;
	}

	@Override
	public synchronized void continueWork() {
		doWork = true;
		notify();
	}

	private synchronized void checkPause() {
		while (!doWork) {
			try {
				wait();
			} catch (InterruptedException ex) {
				interrupt();
				doWork = true;
			}
		}
	}

	private void fileSearch(File myDir, ArrayList<File> list) {
		checkPause();

		if (!myDir.canRead() || !myDir.canExecute()) {
			return;
		}
		File[] myDirContent = myDir.listFiles();
		if (myDirContent == null || myDirContent.length == 0) {
			return;
		}
		for (File entry : myDirContent) {
			if (entry.isDirectory()) {
				fileSearch(entry, list);
				continue;
			}
			if (fileCheckPattern(entry, mask)) {
				list.add(entry);
			}
		}
	}

	private void fileSearchAndStr(File myDir, ArrayList<File> list)
		throws FileNotFoundException {
		checkPause();

		if (!myDir.canRead() || !myDir.canExecute()) {
			return;
		}
		File[] myDirContent = myDir.listFiles();
		if (myDirContent == null || myDirContent.length == 0) {
			return;
		}
		for (File entry : myDirContent) {
			if (entry.isDirectory()) {
				fileSearchAndStr(entry, list);
				continue;
			}
			if (fileCheckPattern(entry, mask) && (fileCheckStr(entry, mask))) {
				list.add(entry);
			}
		}
	}

	private boolean fileCheckPattern(File f, String pattern) {
		return f.getName().toLowerCase().indexOf(pattern.toLowerCase()) > -1;
	}

	private boolean fileCheckStr(File f, String str) throws FileNotFoundException {
		if (!f.isFile() || !f.canRead() || !f.canExecute() || f.length() == 0) {
			return false;
		}
		try (Scanner input = new Scanner(new FileInputStream(f))) {
			while (input.hasNextLine()) {
				String s = input.nextLine();
				if (s.equals(str)) {
					return true;
				}
			}
		}
		return false;
	}
}
Изменен:01 мар 2018 22:24
 
Модераторы:Нет
Сейчас эту тему просматривают:Нет