如何使用SwingWorker制作多线程? [英] How to make multi thread with SwingWorker?

查看:100
本文介绍了如何使用SwingWorker制作多线程?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在这里看到了一个有关多线程的主题:使用Swing的多线程

所以我作为答案 https://stackoverflow.com/a/33908340/11445086

我在下面实现了类似的代码,但是这里没有任何动作.我知道问题出在我的doInBackGround和流程实现上,但我不知道该怎么办.Swing Builder确实是我的新手,对不起这个问题很抱歉.该程序只是使面板中的许多圆圈移动.每个圆都是Swing Worker制作的线程.

这些是我的课程:

机器人课:

package com.mycompany.test;

import java.awt.Color;
import java.util.List;
import java.util.Random;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.SwingWorker;

public class Robot extends SwingWorker< Void ,Integer> {
    public int x;
    public int y;
    public Color color;
    public final int speed = 10;
    Robot(int x , int y , Color color)
    {
        this.x = x;
        this.y = y;
        this.color = color;
    }
    public void move_90()
    {
        this.y += speed;
    }

    public void move_270()
    {
        this.y -= speed;
    }

    public void move_180()
    {
        this.x += speed;
    }

    public void move_0()
    {
        this.x += speed;
    }

    public void move_45()
    {
        this.x += speed;
        this.y += speed;
    }

    public void move_135()
    {
        this.x -= speed;
        this.y += speed;
    }

    public void move_225()
    {
        this.x -= speed;
        this.y -= speed;
    }

    public void move_315()
    {
        this.x += speed;
        this.y -= speed;
    }

    public void move()
    {
        Random temp = new Random();
        int rand = temp.nextInt(8);
        switch(rand)
        {
            case 1: move_0();
            break;
            case 2: move_135();
            break;
            case 3: move_180();
            break;
            case 4: move_225();
            break;
            case 5: move_270();
            break;
            case 6: move_315();
            break;
            case 7: move_45();
            break;
            case 8: move_90();
            break;
        }
    }
    @Override
    protected void process(List<Integer> chunks) {
         while(true)
        {
            move();
            if(x < 40) x = 40;
            if(x > PlayField.width - 40) x = (PlayField.width - 40);
            if(y < 40) y = 40;
            if(y > PlayField.height - 40) y = (PlayField.height - 40);
             try {
                 Thread.sleep(20);
             } catch (InterruptedException ex) {
                 Logger.getLogger(Robot.class.getName()).log(Level.SEVERE, null, ex);
             }
        }
    }

    @Override
    protected Void doInBackground() throws Exception {
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }
}

RobotModel类:

package com.mycompany.test;

import java.awt.Color;
import java.util.LinkedList;

public class RobotModel {
    public static final int MAX = 8;
    public LinkedList<Robot> model = new LinkedList<Robot>();
    public void add_New_Robot()
    {
        Robot temp = new Robot( 40 , 40 , Color.BLUE);
        model.addFirst(temp);
    }
}

PlayField类:

package com.mycompany.test;

import java.awt.Color;

public class PlayField {
    public static int width;
    public static int height;
    public static Color fill_Color;
    PlayField(int width , int height , Color fill_Color)
    {
        this.width = width;
        this.height = height;
        this.fill_Color = fill_Color;
    }
}

RobotWorld类:

package com.mycompany.test;

import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JPanel;

public class RobotWorld extends JPanel {
    public RobotModel robot_Model;

    public RobotWorld(RobotModel robot_Model) {
        super();
        this.robot_Model = robot_Model;
        this.setSize(PlayField.width , PlayField.height);
        this.setVisible(true);
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D graphic = (Graphics2D)g;
        graphic.setBackground(PlayField.fill_Color);
        for(Robot x : robot_Model.model )
        {
            graphic.setColor(x.color);
            graphic.drawOval(x.x, x.y, 40, 40);
        }
    }

}

最后,GameMain类:

package com.mycompany.test;

import java.awt.Color;
import javax.swing.JFrame;

public class GameMain extends JFrame {
    RobotModel a;
    PlayField field;
    public void Game_Start()
    {
        Robot robot = new Robot(100, 100, Color.RED);
        a = new RobotModel();
        RobotWorld world = new RobotWorld(a);
        world.robot_Model.add_New_Robot();
        this.setSize(field.width , field.height);
        this.add(world);
        this.setVisible(true);
        world.repaint();
    }

//    public void gameUpdate(Robot a , PlayField field)
//    {
//        a.move();
//        if(a.x < 40) a.x = 40;
//        if(a.x > field.width - 40) a.x = (field.width - 40);
//        if(a.y < 40) a.y = 40;
//        if(a.y > field.height - 40) a.y = (field.height - 40);
//    }


    public void gameUpdate(){
    Thread gameThread = new Thread(){
        public void run(){
            while(true){
                //execute one time step for the game
//                gameUpdate(a , field);

                //refresh screen
                repaint();

                //give other threads time
                try{
                    Thread.sleep(5);
                }catch(InterruptedException e){
//                    e.printStackTrace();
                }
            }
        }
    };

    gameThread.start();
}



    public static void main(String args[])
    {
        GameMain main = new GameMain();
        main.Game_Start();
        main.gameUpdate();
    }
}

解决方案

问题很多,主要是由于对SwingWorker的实际工作方式缺乏了解.

请记住,更多的线程并不一定总能完成更多的工作.您拥有的线程越多,系统将越难工作.有时,少即是多;)

SwingWorker不太适合此任务.对于WHOLE应用程序,它最多只能执行10个工作程序,并且除非您将更新与事件调度线程正确同步,否则您将无法从中获得任何好处.

通常更简单的解决方案是改为使用Swing Timer.这样可以确保您的更新在EDT中进行,而不会有脏读/写或阻塞EDT的风险.

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.LinkedList;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame();

                PlayField playField = new PlayField(200, 200, Color.DARK_GRAY);
                RobotModel model = new RobotModel();
                model.createNewRobot();

                RobotWorld world = new RobotWorld(playField, model);
                world.start();

                frame.add(world);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class RobotModel {

        public static final int MAX = 8;
        public LinkedList<Robot> bots = new LinkedList<Robot>();

        public void createNewRobot() {
            Robot temp = new Robot(40, 40, Color.BLUE);
            bots.addFirst(temp);
        }
    }

    public class PlayField {

        public int width;
        public int height;
        public Color fill_Color;

        PlayField(int width, int height, Color fill_Color) {
            this.width = width;
            this.height = height;
            this.fill_Color = fill_Color;
        }
    }

    public class RobotWorld extends JPanel {

        public RobotModel model;
        private PlayField playField;

        private Timer timer;

        public RobotWorld(PlayField playField, RobotModel robot_Model) {
            super();
            this.model = robot_Model;
            this.playField = playField;

            setBackground(playField.fill_Color);

            timer = new Timer(5, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent evt) {
                    Rectangle bounds = new Rectangle(new Point(0, 0), getSize());
                    for (Robot bot : model.bots) {
                        bot.move(bounds);
                    }
                    repaint();
                }
            });
        }

        public void start() {
            timer.start();
        }

        public void stop() {
            timer.stop();
        }

        @Override
        public Dimension getPreferredSize() {
            return playField == null ? super.getPreferredSize() : new Dimension(playField.width, playField.height);
        }

        @Override
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            for (Robot bot : model.bots) {
                Graphics2D graphic = (Graphics2D) g.create();
                bot.paint(graphic);
                graphic.dispose();
            }
        }
    }

    public class Robot {

        public int x;
        public int y;
        public Color color;
        public final int speed = 10;
        public int size = 40;

        Robot(int x, int y, Color color) {
            this.x = x;
            this.y = y;
            this.color = color;
        }

        public void paint(Graphics2D g2d) {
            g2d.setColor(color);
            g2d.fillRect(x, y, size, size);
        }

        public void move_90() {
            this.y += speed;
        }

        public void move_270() {
            this.y -= speed;
        }

        public void move_180() {
            this.x += speed;
        }

        public void move_0() {
            this.x += speed;
        }

        public void move_45() {
            this.x += speed;
            this.y += speed;
        }

        public void move_135() {
            this.x -= speed;
            this.y += speed;
        }

        public void move_225() {
            this.x -= speed;
            this.y -= speed;
        }

        public void move_315() {
            this.x += speed;
            this.y -= speed;
        }

        public void move(Rectangle bounds) {
            Random temp = new Random();
            int rand = temp.nextInt(8);
            switch (rand) {
                case 1:
                    move_0();
                    break;
                case 2:
                    move_135();
                    break;
                case 3:
                    move_180();
                    break;
                case 4:
                    move_225();
                    break;
                case 5:
                    move_270();
                    break;
                case 6:
                    move_315();
                    break;
                case 7:
                    move_45();
                    break;
                case 8:
                    move_90();
                    break;
            }

            if (x < bounds.x) {
                x = bounds.x;
            } else if (x + size > bounds.x + bounds.width) {
                x = bounds.x + bounds.width - size;
            }
            if (y < bounds.y) {
                y = bounds.y;
            } else if (y + size > bounds.y + bounds.height) {
                y = bounds.y + bounds.height - size;
            }
        }

    }
}

有关更多详细信息,请参见如何使用Swing计时器

如果您不愿意使用SwingWorker,那么您应该花时间阅读Multi-threading with Swing

So I do as the answer https://stackoverflow.com/a/33908340/11445086

I implement like codes below but there's not anything movement here. I know the problem is about my doInBackGround and process implementation but I don't know how to do.I'm really new with Swing Builder so sorry if the question's silly. The program just makes many circles moving in the Panel. And each circle is a Thread that be made by Swing Worker.

these're my classes:

Robot class :

package com.mycompany.test;

import java.awt.Color;
import java.util.List;
import java.util.Random;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.SwingWorker;

public class Robot extends SwingWorker< Void ,Integer> {
    public int x;
    public int y;
    public Color color;
    public final int speed = 10;
    Robot(int x , int y , Color color)
    {
        this.x = x;
        this.y = y;
        this.color = color;
    }
    public void move_90()
    {
        this.y += speed;
    }

    public void move_270()
    {
        this.y -= speed;
    }

    public void move_180()
    {
        this.x += speed;
    }

    public void move_0()
    {
        this.x += speed;
    }

    public void move_45()
    {
        this.x += speed;
        this.y += speed;
    }

    public void move_135()
    {
        this.x -= speed;
        this.y += speed;
    }

    public void move_225()
    {
        this.x -= speed;
        this.y -= speed;
    }

    public void move_315()
    {
        this.x += speed;
        this.y -= speed;
    }

    public void move()
    {
        Random temp = new Random();
        int rand = temp.nextInt(8);
        switch(rand)
        {
            case 1: move_0();
            break;
            case 2: move_135();
            break;
            case 3: move_180();
            break;
            case 4: move_225();
            break;
            case 5: move_270();
            break;
            case 6: move_315();
            break;
            case 7: move_45();
            break;
            case 8: move_90();
            break;
        }
    }
    @Override
    protected void process(List<Integer> chunks) {
         while(true)
        {
            move();
            if(x < 40) x = 40;
            if(x > PlayField.width - 40) x = (PlayField.width - 40);
            if(y < 40) y = 40;
            if(y > PlayField.height - 40) y = (PlayField.height - 40);
             try {
                 Thread.sleep(20);
             } catch (InterruptedException ex) {
                 Logger.getLogger(Robot.class.getName()).log(Level.SEVERE, null, ex);
             }
        }
    }

    @Override
    protected Void doInBackground() throws Exception {
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }
}

RobotModel class :

package com.mycompany.test;

import java.awt.Color;
import java.util.LinkedList;

public class RobotModel {
    public static final int MAX = 8;
    public LinkedList<Robot> model = new LinkedList<Robot>();
    public void add_New_Robot()
    {
        Robot temp = new Robot( 40 , 40 , Color.BLUE);
        model.addFirst(temp);
    }
}

PlayField class :

package com.mycompany.test;

import java.awt.Color;

public class PlayField {
    public static int width;
    public static int height;
    public static Color fill_Color;
    PlayField(int width , int height , Color fill_Color)
    {
        this.width = width;
        this.height = height;
        this.fill_Color = fill_Color;
    }
}

RobotWorld class :

package com.mycompany.test;

import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JPanel;

public class RobotWorld extends JPanel {
    public RobotModel robot_Model;

    public RobotWorld(RobotModel robot_Model) {
        super();
        this.robot_Model = robot_Model;
        this.setSize(PlayField.width , PlayField.height);
        this.setVisible(true);
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D graphic = (Graphics2D)g;
        graphic.setBackground(PlayField.fill_Color);
        for(Robot x : robot_Model.model )
        {
            graphic.setColor(x.color);
            graphic.drawOval(x.x, x.y, 40, 40);
        }
    }

}

And finally , GameMain class :

package com.mycompany.test;

import java.awt.Color;
import javax.swing.JFrame;

public class GameMain extends JFrame {
    RobotModel a;
    PlayField field;
    public void Game_Start()
    {
        Robot robot = new Robot(100, 100, Color.RED);
        a = new RobotModel();
        RobotWorld world = new RobotWorld(a);
        world.robot_Model.add_New_Robot();
        this.setSize(field.width , field.height);
        this.add(world);
        this.setVisible(true);
        world.repaint();
    }

//    public void gameUpdate(Robot a , PlayField field)
//    {
//        a.move();
//        if(a.x < 40) a.x = 40;
//        if(a.x > field.width - 40) a.x = (field.width - 40);
//        if(a.y < 40) a.y = 40;
//        if(a.y > field.height - 40) a.y = (field.height - 40);
//    }


    public void gameUpdate(){
    Thread gameThread = new Thread(){
        public void run(){
            while(true){
                //execute one time step for the game
//                gameUpdate(a , field);

                //refresh screen
                repaint();

                //give other threads time
                try{
                    Thread.sleep(5);
                }catch(InterruptedException e){
//                    e.printStackTrace();
                }
            }
        }
    };

    gameThread.start();
}



    public static void main(String args[])
    {
        GameMain main = new GameMain();
        main.Game_Start();
        main.gameUpdate();
    }
}

解决方案

The problems are multiple, mostly to do with a lack of understand over how SwingWorker actually works.

Remember, more threads doesn't always more more work. The more threads you have, the harder the system will have to work. Sometimes, less is more ;)

SwingWorker is not well suited to this task. It will only allow a maximum of 10 workers to execute, for the WHOLE app and, unless you're synchronising your updates with the Event Dispatching Thread properly, you'd not be gaining any benefit from it.

A generally simpler solution would be to make use of a Swing Timer instead. This will ensure your updates are carried out within the EDT without the risk of dirty read/writes or blocking the EDT.

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.LinkedList;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame();

                PlayField playField = new PlayField(200, 200, Color.DARK_GRAY);
                RobotModel model = new RobotModel();
                model.createNewRobot();

                RobotWorld world = new RobotWorld(playField, model);
                world.start();

                frame.add(world);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class RobotModel {

        public static final int MAX = 8;
        public LinkedList<Robot> bots = new LinkedList<Robot>();

        public void createNewRobot() {
            Robot temp = new Robot(40, 40, Color.BLUE);
            bots.addFirst(temp);
        }
    }

    public class PlayField {

        public int width;
        public int height;
        public Color fill_Color;

        PlayField(int width, int height, Color fill_Color) {
            this.width = width;
            this.height = height;
            this.fill_Color = fill_Color;
        }
    }

    public class RobotWorld extends JPanel {

        public RobotModel model;
        private PlayField playField;

        private Timer timer;

        public RobotWorld(PlayField playField, RobotModel robot_Model) {
            super();
            this.model = robot_Model;
            this.playField = playField;

            setBackground(playField.fill_Color);

            timer = new Timer(5, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent evt) {
                    Rectangle bounds = new Rectangle(new Point(0, 0), getSize());
                    for (Robot bot : model.bots) {
                        bot.move(bounds);
                    }
                    repaint();
                }
            });
        }

        public void start() {
            timer.start();
        }

        public void stop() {
            timer.stop();
        }

        @Override
        public Dimension getPreferredSize() {
            return playField == null ? super.getPreferredSize() : new Dimension(playField.width, playField.height);
        }

        @Override
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            for (Robot bot : model.bots) {
                Graphics2D graphic = (Graphics2D) g.create();
                bot.paint(graphic);
                graphic.dispose();
            }
        }
    }

    public class Robot {

        public int x;
        public int y;
        public Color color;
        public final int speed = 10;
        public int size = 40;

        Robot(int x, int y, Color color) {
            this.x = x;
            this.y = y;
            this.color = color;
        }

        public void paint(Graphics2D g2d) {
            g2d.setColor(color);
            g2d.fillRect(x, y, size, size);
        }

        public void move_90() {
            this.y += speed;
        }

        public void move_270() {
            this.y -= speed;
        }

        public void move_180() {
            this.x += speed;
        }

        public void move_0() {
            this.x += speed;
        }

        public void move_45() {
            this.x += speed;
            this.y += speed;
        }

        public void move_135() {
            this.x -= speed;
            this.y += speed;
        }

        public void move_225() {
            this.x -= speed;
            this.y -= speed;
        }

        public void move_315() {
            this.x += speed;
            this.y -= speed;
        }

        public void move(Rectangle bounds) {
            Random temp = new Random();
            int rand = temp.nextInt(8);
            switch (rand) {
                case 1:
                    move_0();
                    break;
                case 2:
                    move_135();
                    break;
                case 3:
                    move_180();
                    break;
                case 4:
                    move_225();
                    break;
                case 5:
                    move_270();
                    break;
                case 6:
                    move_315();
                    break;
                case 7:
                    move_45();
                    break;
                case 8:
                    move_90();
                    break;
            }

            if (x < bounds.x) {
                x = bounds.x;
            } else if (x + size > bounds.x + bounds.width) {
                x = bounds.x + bounds.width - size;
            }
            if (y < bounds.y) {
                y = bounds.y;
            } else if (y + size > bounds.y + bounds.height) {
                y = bounds.y + bounds.height - size;
            }
        }

    }
}

See How to Use Swing Timers for more details

If you're hell bent on using a SwingWorker, then you should take the time to read through Worker Threads and SwingWorker

这篇关于如何使用SwingWorker制作多线程?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆