javafx线程学习_javafx线程封装了线程池吗 - CSDN
  • 一个小球运动的学习案例(Javafx线程) package 小球运动; import javafx.application.Application; import javafx.application.Platform; import javafx.event.ActionEvent; import javafx.event....

    一个小球运动的学习案例(Javafx 和 线程)

    package 小球运动;
    
    
    
    
    
    
    import javafx.application.Application;
    import javafx.application.Platform;
    import javafx.event.ActionEvent;
    import javafx.event.EventHandler;
    import javafx.scene.Group;
    import javafx.scene.Scene;
    import javafx.scene.control.Button;
    import javafx.scene.layout.BorderPane;
    import javafx.scene.layout.FlowPane;
    import javafx.scene.paint.Color;
    import javafx.scene.shape.Circle;
    import javafx.stage.Stage;
    
    import java.io.*;
    import java.util.LinkedList;
    import java.util.List;
    
    class Ball extends Circle implements Serializable {
    
        double x;
    
        double y;
    
        double r;
    
        int color;
    
    
    
        public Ball() {
    
            setX(10 + 580 * Math.random());
    
            setY(10 + 580 * Math.random());
            setR(10 +
                    40 * Math.random());
    
            setColor((int)(Math.random()*65536));
    
            try {
    
                setFill(Color.valueOf("#" + Integer.toHexString(getColor())));
    
            } catch (IllegalArgumentException e) {
    
                setFill(Color.RED);
    
            }
    
        }
    
    
    
        public Ball(double x, double y, double r, int color) {
    
            super();
    
            this.x = x;
    
            this.y = y;
    
            this.r = r;
    
            this.color = color;
    
        }
    
    
    
        public double getX() {
    
            return x;
    
        }
    
        public void setX(double x) {
    
            this.setCenterX(x);
    
            this.x = x;
    
        }
    
        public double getY() {
    
            return y;
    
        }
    
        public void setY(double y) {
    
            this.setCenterY(y);
    
            this.y = y;
    
        }
    
        public double getR() {
    
            return r;
    
        }
    
        public void setR(double r) {
    
            this.setRadius(r);
    
            this.r = r;
    
        }
    
        public int getColor() {
    
            return color;
    
        }
    
        public void setColor(int color) {
    
            this.color = color;
    
        }
    
        public void setCircle(){
    
            setRadius(getR());
    
            setCenterX(getX());
    
            setCenterY(getY());
    
            try {
    
                setFill(Color.valueOf("#" + Integer.toHexString(getColor())));
    
            } catch (IllegalArgumentException e) {
    
                setFill(Color.RED);
    
            }
    
        }
    
    
    
    }
    
    
    public class Main extends Application {
    
        ObjectOutputStream oos;
    
        ObjectInputStream ois;
    
        Group group;
    
        List<Ball> list;
    
        volatile boolean flag = true;
    
    
        public void mInit() {
    
            list = new LinkedList<Ball>();
    
            for (int i = 0; i < 10; i++) {
    
                Ball ball = new Ball();
    
                list.add(ball);
    
                group.getChildren().addAll(ball);
    
            }
    
        }
    
    
        class T extends Thread {
    
            @Override
    
            public void run() {
    
                for (int i = 0; i < 60; i++) {
    
                    if (!flag)
    
                        break;
    
                    Platform.runLater(new Runnable() {
    
                        @Override
    
                        public void run() {
    
                            for (Ball ball : list) {
    
                                ball.setX(ball.getX() + 36 * Math.random());
    
                                ball.setY(ball.getY() + 36 * Math.random());
    
                            }
    
                        }
    
                    });
    
                    try {
    
                        Thread.sleep(300);
    
                    } catch (InterruptedException e) {
    
                        e.printStackTrace();
    
                    }
    
                }
    
            }
    
        }
    
    
        @Override
    
        public void start(Stage primaryStage) {
    
            try {
    
                BorderPane root = new BorderPane();
    
                Button button0 = new Button("开始运动");
    
                Button button1 = new Button("保存小球目前状态");
    
                Button button2 = new Button("载入小球保存状态");
    
                Button button3 = new Button("停止运动并清除小球");
    
                FlowPane pane = new FlowPane();
    
                root.setTop(pane);
    
                pane.getChildren().add(button0);
    
                pane.getChildren().add(button1);
    
                pane.getChildren().add(button2);
    
                pane.getChildren().add(button3);
    
                group = new Group();
    
                root.setCenter(group);
    
                Scene scene = new Scene(root);
    
    //            scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
    
                primaryStage.setScene(scene);
    
                primaryStage.show();
    
                primaryStage.setMaximized(true);
    
                mInit();
    
    
                //让小球开始运动
    
                button0.setOnAction(new EventHandler<ActionEvent>() {
    
                    @Override
    
                    public void handle(ActionEvent event) {
    
                        flag = true;
    
                        T t = new T();
    
                        t.start();
    
                    }
    
                });
    
                //保存小球的状态
    
                button1.setOnAction(new EventHandler<ActionEvent>() {
    
                    @Override
    
                    public void handle(ActionEvent arg0) {
    
                        try {
    
                            oos = new ObjectOutputStream(new FileOutputStream("1.txt"));
                            oos.writeObject(list);
    
                            oos.close();
    
                        } catch (FileNotFoundException e1) {
    
                            e1.printStackTrace();
    
                        } catch (IOException e1) {
    
                            e1.printStackTrace();
    
                        }
    
                    }
    
                });
    
                //读取小球的状态
    
                button2.setOnAction(new EventHandler<ActionEvent>() {
    
                    @Override
    
                    public void handle(ActionEvent event) {
    
                        try {
    
                            ois = new ObjectInputStream(new FileInputStream("1.txt"));
    
                            list = (List<Ball>) ois.readObject();
    
                            ois.close();
    
                        } catch (IOException | ClassNotFoundException e1) {
    
                            e1.printStackTrace();
    
                        }
    
                        for (int i = 0; i < list.size(); i++) {
    
                            Ball ball = list.get(i);
    
                            ball.setCircle();
    
                            group.getChildren().add(ball);
    
                        }
    
                    }
    
    
                });
    
                //让小球运动线程停止并清除界面上的小球
    
                button3.setOnAction(new EventHandler<ActionEvent>() {
    
                    @Override
    
                    public void handle(ActionEvent event) {
    
                        flag = false;
    
                        group.getChildren().clear();
    
                    }
    
                });
    
    
            } catch (Exception e) {
    
                e.printStackTrace();
    
            }
    
        }
    
    
        public static void main(String[] args) {
    
            launch(args);
    
        }
    
    }
    
    
    
    
    

    1.volatile和static的区别
    这里找到了很好的解释
    (原文 https://blog.csdn.net/frankarmstrong/article/details/55657290)
    在这里插入图片描述

    2.就是关于platform.runlater

    在这里插入图片描述

    我参照以下文章来了解它
    https://www.it1352.com/963466.html
    http://www.voidcn.com/article/p-neecqvdj-bsp.html

    展开全文
  • 之前看了篇blog学习了一下如何使用JavaFX线程JavaFX如何做多线程编程 里面讲到用Task或者Service来启用FX子线程以更新界面。最近尝试了下用Task,但一直报错: “Not on FX application thread” 研究了半天...

    之前看了篇blog学习了一下如何使用JavaFX多线程:

    JavaFX如何做多线程编程

    里面讲到用Task或者Service来启用FX子线程以更新界面。最近尝试了下用Task,但一直报错:

    “Not on FX application thread”

    研究了半天,发现Task类里面的call方法还是使用传统子线程做处理

    只有successed, running, scheduled, cancelled, failed等方法才是使用JavaFX线程工作的

    因此要更新UI,只要重写这些方法即可:

    button.setOnAction((event) -> {
    
        new Thread(new Task<Void>() {
    
            // call方法里面的线程非JavaFX线程
            @Override
            protected Void call() throws Exception {
                button.setText("1xxx");  // 这里会报错
                return null;
            }
    
            @Override
            protected void succeeded() {
                button.setText("xxx");
                System.out.println(Thread.currentThread());
    
                super.succeeded();
            }
    
        }).start();
    
    });
    展开全文
  • 一、两个实现多线程的方法 1、 直接继承Thread类, 然后重写run()方法。 2、 实现Runnable()接口, 重写run()方法。 推荐使用第二种方法。 二、 线程中的各种方法 1、 Thread.yield() 方法 * Thread.yield...

    一、两个实现多线程的方法

      1、 直接继承Thread类, 然后重写run()方法。

      2、 实现Runnable()接口, 重写run()方法。

    推荐使用第二种方法。

    二、 线程中的各种方法

      1、 Thread.yield() 方法

     *  Thread.yield()方法,程序运行到这句话的时候,会让出当前线程,让其他线程执行,把执行权交给其他线程,使当前线程由运行状态变为可执行状态,但是并不是说下一次一定不是执行这个线程,而是CPU从可执行状态的线程中选一个运行。 

    
    public class PrintNum implements Runnable  {
    	
        private int num;
        
        
        public PrintNum(int num) {
    		this.num = num;
    	}
    
    	@Override
        public void run() {
        	for(int i = 0 ; i < num ; i++) {
        		System.out.println(i);
        		/*
        		 *  Thread.yield()方法,程序运行到这句话的时候,会让出当前线程,让其他线程执行,
        		 *  把执行权交给其他线程,使当前线程由运行状态变为可执行状态,但是并不是说下一次一
        		 *  定不是执行这个线程,而是CPU从可执行状态的线程中选一个运行
        		 */
        		Thread.yield();		
        		
        	}
        }
    	
    }
    

    当程序运行到Thread.yield()方法时,该线程会让出CPU资源,进入可执行状态,也就是就绪状态,等待CPU分配资源。

      2、 Thread.sleep() 方法  

      Thread.sleep()方法,传入一个参数,millis, 为一个int 类型的变量,为毫秒,让进程从运行状态进入中断状态, 经过millsecond毫秒之后,重新进入到线程队列变成可执行状态,等CPU分配。

      3、 join()方法

      实例方法, 调用该实例的join() 方法,就会将当前运行的线程阻塞住,等待调用join()方法的线程运行结束之后再重新运行该线程。 

      4、 interrupt() 方法 和Thread.interrupted() 方法

     

    // Demo1.java
    import jdk.nashorn.internal.runtime.regexp.joni.exception.InternalException;
    
    public class Demo1 {
        public static void main(String[] args) throws InterruptedException {
        	
        	
        	Thread t1 = new Thread(new PrintChar('A', 200));
    //    	Thread t2 = new Thread(new PrintChar('B', 100));
    //    	Thread t3 = new Thread(new PrintNum(100));
        	t1.start();
    //    	t2.start();
    //    	t3.start();
        	
        	
        	
        	/*
        	 *  setPriority()方法,设置优先级,值为1 - 10,10 为最高, 但是并不是设置了低的优先级就最后执行,而是概率的问题
        	 */
    //    	t1.setPriority(Thread.MAX_PRIORITY);
        	
        	
        	/*
        	 *  threadInstance.join()方法,阻塞当前线程,等threadInstance线程执行完毕之后再执行当前的线程
        	 */
        	
        	
        	for(int i = 0; i < 200 ; i++) {
        		System.out.println(i);
        		if (i == 50 ) {
        			/*
        			 *   interrupt()方法经常用来“吵醒” 休眠的线程, 当一些线程调用了sleep() 方法处于休眠状态的时候,
        			 *   一个占有CPU资源的线程可以让休眠的线程跳用interrupt()方法“吵醒”自己,让线程结束休眠,重新排队
        			 *   等待CPU的资源
        			 *   
        			 *   interrupt() 实际意义上是设置了一个标志位,并不能终止t1线程,只是通知t1线程把中断标志给修改一下,
        			 *   中断标志平常是false,但是调用了interrupt()方法之后,变为true, 并不是直接把t1线程给终止了,t1
        			 *   会不断检查这个标志位,看看是不是有人想要让线程终止,如果有人让线程终止,就停止,但是是否终止决定权
        			 *   在t1受伤
        			 */
    //    	         t1.interrupt();
        		}
        	}
        	
        }
    }
    
    //PrintChar.java
    
    public class PrintChar implements Runnable {
    
    	private char alpha;
    
    	private int times;
    
    	public PrintChar(char alpha, int times) {
    		this.alpha = alpha;
    		this.times = times;
    	}
    
    	@Override
    	public void run() {
    		/*
    		 * Thread.sleep()方法,传入一个参数,millis, 为一个int 类型的变量,为毫秒,让进程从运行状态进入中断状态,
    		 * 进过millsecond毫秒之后,重新进入到线程队列变成可执行状态,等CPU分配。
    		 */
    		try {
    			int i = 0;
    			for (i = 0; i < times; i++) {
    //				if(Thread.currentThread().isInterrupted()) {
    //					break;
    //				}
    				if(Thread.interrupted()) {
    				/*
    				 *  Thread.interrupted()静态方法,返回一个boolean类型,返回中断结果,查看是否有其他线程调用了(线程实例.interrupt())方法,
    				 *  并重置该线程的中断标志位,变成false. (先返回之前的类型, 后重置为false) 
    				 */
    					System.out.println(Thread.currentThread().isInterrupted());
    				}
    				System.out.println(alpha);
    //				if (i >= 50) {
    //					Thread.sleep(3000);
    //				}
    			}
    			System.out.println(i + "   打印完了");
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    	}
    }
    
    //PrintNum.java
    
    
    public class PrintNum implements Runnable  {
    	
        private int num;
        
        
        public PrintNum(int num) {
    		this.num = num;
    	}
    
    	@Override
        public void run() {
        	for(int i = 0 ; i < num ; i++) {
        		System.out.println(i);
        		/*
        		 *  Thread.yield()方法,程序运行到这句话的时候,会让出当前线程,让其他线程执行,
        		 *  把执行权交给其他线程,使当前线程由运行状态变为可执行状态,但是并不是说下一次一
        		 *  定不是执行这个线程,而是CPU从可执行状态的线程中选一个运行
        		 */
        		Thread.yield();		
        		
        	}
        }
    	
    }
    

     

    展开全文
  • 多个线程如果共享资源的情况下, 很容易的就会导致资源出现混乱,就以买票的程序为例子,先创建一个SellTicket对象,设置总票数为100张的情况下,设置四个窗口售卖这一百张票。 // SellTicket.java import ...

      一、 synchronized

    多个线程如果共享资源的情况下, 很容易的就会导致资源出现混乱,就以买票的程序为例子,先创建一个SellTicket对象,设置总票数为100张的情况下,设置四个窗口售卖这一百张票。

    // SellTicket.java
    import com.sun.org.apache.xml.internal.resolver.Catalog;
    
    public class SellTicket implements Runnable {
    
    	private int tickteCount = 100;
    
    	@Override
    	public void run() {
    		try {
    			while (tickteCount > 0) {
    				sellTicket();
    				// 让线程睡一会,以免太快把票卖完
    				Thread.sleep(100);
    			}
    		} catch (InterruptedException e) {
    			e.printStackTrace();
    		}
    	}
    
    	private void sellTicket() {
    		if (tickteCount > 0) {
    			tickteCount--;
    			System.out.println(Thread.currentThread().getName() + "买票, " + "还剩" + tickteCount + "张票。");
    		} else {
    			System.out.println("票卖完了");
    		}
    	}
    }
    
    //Demo1.java
    import jdk.nashorn.internal.runtime.regexp.joni.exception.InternalException;
    
    public class Demo1 {
        public static void main(String[] args) throws InterruptedException {
        	
        	
        	// 让多个线程操作一个对象的资源,而不是new多个SellTicket() 对象.
        	SellTicket ticket = new SellTicket();
       
        	Thread t1 = new Thread(ticket,"窗口1");
        	Thread t2 = new Thread(ticket,"窗口2");
        	Thread t3 = new Thread(ticket,"窗口3");
        	Thread t4 = new Thread(ticket,"窗口4");
        	
        	t1.start();
        	t2.start();
        	t3.start();
        	t4.start(); 
        	
        }
        
    }
    `

      程序运行之后,出现如下结果:

    窗口1买票, 还剩98张票。
    窗口2买票, 还剩98张票。
    窗口3买票, 还剩97张票。
    窗口4买票, 还剩96张票。
    窗口1买票, 还剩94张票。
    窗口3买票, 还剩93张票。
    窗口2买票, 还剩94张票。
    窗口4买票, 还剩92张票。
    窗口1买票, 还剩90张票。
    窗口4买票, 还剩89张票。
    窗口2买票, 还剩90张票。
    窗口3买票, 还剩90张票。
    窗口1买票, 还剩87张票。
    窗口3买票, 还剩86张票。
    窗口4买票, 还剩87张票。
    窗口2买票, 还剩87张票。
    窗口1买票, 还剩85张票。
    窗口2买票, 还剩82张票。
    窗口4买票, 还剩83张票。
    窗口3买票, 还剩83张票。
    窗口4买票, 还剩81张票。
    窗口3买票, 还剩80张票。
    窗口2买票, 还剩81张票。
    窗口1买票, 还剩81张票。
    窗口2买票, 还剩78张票。
    窗口1买票, 还剩77张票。
    窗口3买票, 还剩78张票。
    窗口4买票, 还剩78张票。
    窗口2买票, 还剩75张票。
    窗口4买票, 还剩73张票。
    窗口3买票, 还剩74张票。
    窗口1买票, 还剩75张票。
    窗口2买票, 还剩72张票。
    窗口1买票, 还剩69张票。
    窗口3买票, 还剩70张票。
    窗口4买票, 还剩71张票。
    窗口2买票, 还剩67张票。
    窗口4买票, 还剩65张票。
    窗口3买票, 还剩66张票。
    窗口1买票, 还剩67张票。
    窗口4买票, 还剩64张票。
    窗口2买票, 还剩64张票。
    窗口3买票, 还剩62张票。
    窗口1买票, 还剩62张票。
    窗口4买票, 还剩60张票。
    窗口1买票, 还剩59张票。
    窗口2买票, 还剩60张票。
    窗口3买票, 还剩60张票。
    窗口4买票, 还剩58张票。
    窗口3买票, 还剩55张票。
    窗口1买票, 还剩56张票。
    窗口2买票, 还剩56张票。
    窗口4买票, 还剩54张票。
    窗口3买票, 还剩53张票。
    窗口2买票, 还剩51张票。
    窗口1买票, 还剩52张票。
    窗口4买票, 还剩50张票。
    窗口2买票, 还剩49张票。
    窗口1买票, 还剩48张票。
    窗口3买票, 还剩48张票。
    窗口4买票, 还剩47张票。
    窗口2买票, 还剩46张票。
    窗口1买票, 还剩45张票。
    窗口3买票, 还剩44张票。
    窗口4买票, 还剩43张票。
    窗口2买票, 还剩42张票。
    窗口3买票, 还剩40张票。
    窗口1买票, 还剩41张票。
    窗口4买票, 还剩39张票。
    窗口3买票, 还剩37张票。
    窗口1买票, 还剩36张票。
    窗口2买票, 还剩37张票。
    窗口4买票, 还剩35张票。
    窗口2买票, 还剩33张票。
    窗口1买票, 还剩32张票。
    窗口3买票, 还剩32张票。
    窗口4买票, 还剩31张票。
    窗口1买票, 还剩30张票。
    窗口2买票, 还剩29张票。
    窗口3买票, 还剩30张票。
    窗口4买票, 还剩28张票。
    窗口1买票, 还剩27张票。
    窗口3买票, 还剩25张票。
    窗口2买票, 还剩26张票。
    窗口4买票, 还剩24张票。
    窗口1买票, 还剩23张票。
    窗口2买票, 还剩21张票。
    窗口3买票, 还剩22张票。
    窗口4买票, 还剩20张票。
    窗口1买票, 还剩19张票。
    窗口3买票, 还剩18张票。
    窗口2买票, 还剩19张票。
    窗口4买票, 还剩17张票。
    窗口1买票, 还剩16张票。
    窗口3买票, 还剩16张票。
    窗口2买票, 还剩15张票。
    窗口4买票, 还剩14张票。
    窗口1买票, 还剩13张票。
    窗口2买票, 还剩12张票。
    窗口3买票, 还剩12张票。
    窗口4买票, 还剩11张票。
    窗口1买票, 还剩10张票。
    窗口3买票, 还剩8张票。
    窗口2买票, 还剩9张票。
    窗口4买票, 还剩7张票。
    窗口3买票, 还剩5张票。
    窗口2买票, 还剩4张票。
    窗口1买票, 还剩5张票。
    窗口4买票, 还剩3张票。
    窗口2买票, 还剩2张票。
    窗口1买票, 还剩1张票。
    窗口3买票, 还剩2张票。
    窗口4买票, 还剩0张票。
    

      很明显, 窗口重复售卖了同一张票,是因为在下面这段代码中:

    if (tickteCount > 0) {
    			// 有可能CPU在这个时候切换了,已经进入到另外一个线程里面。
    			tickteCount--;
    			System.out.println(Thread.currentThread().getName() + "买票, " + "还剩" + tickteCount + "张票。");
    		} else {
    			System.out.println("票卖完了");
    		}

    线程1 可能已经进入到if里面了,但是CPU资源分配到其他线程,导致该线程停在这里,资源就会出现混乱。

    解决方法:在synchronized(Object)里面写代码。

    synchronized(Object),运行到该代码块的线程回去尝试获取Object的锁, 如果获取到了,就会执行synchronized{}里面的代码,否则就会不执行。

    //SellTicket.java
    import com.sun.org.apache.xml.internal.resolver.Catalog;
    
    public class SellTicket implements Runnable {
    
    	private int tickteCount = 100;
    	
    	private Object obj = new Object();
    
    	@Override
    	public void run() {
    		try {
    			while (tickteCount > 0) {
    				sellTicket();
    				// 让线程睡一会,以免太快把票卖完
    				Thread.sleep(100);
    			}
    		} catch (InterruptedException e) {
    			e.printStackTrace();
    		}
    	}
    
    	private void sellTicket() {
    		synchronized (obj) {  // 同步代码块 锁 任何一个对象
    			if (tickteCount > 0) {
    				tickteCount--;
    				System.out.println(Thread.currentThread().getName() + "买票, " + "还剩" + tickteCount + "张票。");
    			} else {
    				System.out.println("票卖完了");
    			}
    		}
    		
    	}
    }
    
    
    运行结果:
    窗口1买票, 还剩99张票。
    窗口4买票, 还剩98张票。
    窗口3买票, 还剩97张票。
    窗口2买票, 还剩96张票。
    窗口4买票, 还剩95张票。
    窗口3买票, 还剩94张票。
    窗口2买票, 还剩93张票。
    窗口1买票, 还剩92张票。
    窗口3买票, 还剩91张票。
    窗口2买票, 还剩90张票。
    窗口1买票, 还剩89张票。
    窗口4买票, 还剩88张票。
    窗口3买票, 还剩87张票。
    窗口1买票, 还剩86张票。
    窗口2买票, 还剩85张票。
    窗口4买票, 还剩84张票。
    窗口1买票, 还剩83张票。
    窗口2买票, 还剩82张票。
    窗口3买票, 还剩81张票。
    窗口4买票, 还剩80张票。
    窗口1买票, 还剩79张票。
    窗口3买票, 还剩78张票。
    窗口2买票, 还剩77张票。
    窗口4买票, 还剩76张票。
    窗口3买票, 还剩75张票。
    窗口2买票, 还剩74张票。
    窗口1买票, 还剩73张票。
    窗口4买票, 还剩72张票。
    窗口3买票, 还剩71张票。
    窗口1买票, 还剩70张票。
    窗口2买票, 还剩69张票。
    窗口4买票, 还剩68张票。
    窗口3买票, 还剩67张票。
    窗口2买票, 还剩66张票。
    窗口1买票, 还剩65张票。
    窗口4买票, 还剩64张票。
    窗口3买票, 还剩63张票。
    窗口2买票, 还剩62张票。
    窗口1买票, 还剩61张票。
    窗口4买票, 还剩60张票。
    窗口3买票, 还剩59张票。
    窗口1买票, 还剩58张票。
    窗口2买票, 还剩57张票。
    窗口4买票, 还剩56张票。
    窗口3买票, 还剩55张票。
    窗口2买票, 还剩54张票。
    窗口1买票, 还剩53张票。
    窗口4买票, 还剩52张票。
    窗口3买票, 还剩51张票。
    窗口1买票, 还剩50张票。
    窗口2买票, 还剩49张票。
    窗口4买票, 还剩48张票。
    窗口3买票, 还剩47张票。
    窗口2买票, 还剩46张票。
    窗口1买票, 还剩45张票。
    窗口4买票, 还剩44张票。
    窗口3买票, 还剩43张票。
    窗口1买票, 还剩42张票。
    窗口2买票, 还剩41张票。
    窗口4买票, 还剩40张票。
    窗口3买票, 还剩39张票。
    窗口2买票, 还剩38张票。
    窗口1买票, 还剩37张票。
    窗口4买票, 还剩36张票。
    窗口3买票, 还剩35张票。
    窗口1买票, 还剩34张票。
    窗口2买票, 还剩33张票。
    窗口4买票, 还剩32张票。
    窗口3买票, 还剩31张票。
    窗口1买票, 还剩30张票。
    窗口2买票, 还剩29张票。
    窗口4买票, 还剩28张票。
    窗口3买票, 还剩27张票。
    窗口1买票, 还剩26张票。
    窗口2买票, 还剩25张票。
    窗口4买票, 还剩24张票。
    窗口3买票, 还剩23张票。
    窗口1买票, 还剩22张票。
    窗口2买票, 还剩21张票。
    窗口4买票, 还剩20张票。
    窗口3买票, 还剩19张票。
    窗口2买票, 还剩18张票。
    窗口1买票, 还剩17张票。
    窗口4买票, 还剩16张票。
    窗口3买票, 还剩15张票。
    窗口2买票, 还剩14张票。
    窗口1买票, 还剩13张票。
    窗口4买票, 还剩12张票。
    窗口3买票, 还剩11张票。
    窗口2买票, 还剩10张票。
    窗口1买票, 还剩9张票。
    窗口4买票, 还剩8张票。
    窗口3买票, 还剩7张票。
    窗口2买票, 还剩6张票。
    窗口1买票, 还剩5张票。
    窗口4买票, 还剩4张票。
    窗口3买票, 还剩3张票。
    窗口2买票, 还剩2张票。
    窗口1买票, 还剩1张票。
    窗口4买票, 还剩0张票。
    

    另外,也可以在方法上面加上synchronized, 使得该方法变成一个同步方法,synchronized 获取的锁就是从本身这个对象的锁获取的。

    private synchronized void sellTicket() {
    //		synchronized (obj) {  // 同步代码块 锁 任何一个对象
    			if (tickteCount > 0) {
    				tickteCount--;
    				System.out.println(Thread.currentThread().getName() + "买票, " + "还剩" + tickteCount + "张票。");
    			} else {
    				System.out.println("票卖完了");
    			}
    //		}
    		
    	}

    二、线程之间的唤醒(三个方法必须写在synchronized代码块里面)

     

    // Waiter.java
    
    public class Waiter implements Runnable {
    	
    	
    	private Message message;// 使用message来加锁
    	
    	public Waiter(Message message) {
    	    this.message = message;
    	}
    
    	@Override
    	public void run() {
    		
    		String name = Thread.currentThread().getName();
    		synchronized (message) {
    		    try {
    		    	System.out.println(name + " 等待时间" + System.currentTimeMillis());
    		    	message.wait();
    		    	System.out.println(message.getMessage() + System.currentTimeMillis());
    		    }catch (InterruptedException e) {
    			    e.printStackTrace();
    			}
    		}
    	}
    }
    
    //Notifier.java
    
    public class Notifier implements Runnable{
    	
    	Message message;
    	
        public Notifier(Message message) {
        	this.message = message;
        }
    
    	@Override
    	public void run() {
    		String name = Thread.currentThread().getName();
    		
    		synchronized(message) {
    			message.setMessage("唤醒线程工作");
    			message.notify();
    		}
    	}
        
    }
    
    //Demo1.java
    import jdk.nashorn.internal.runtime.regexp.joni.exception.InternalException;
    
    public class Demo1 {
        public static void main(String[] args) throws InterruptedException {
        	
        	Message message = new Message("锁");
        	
        	Waiter waiter1 = new Waiter(message);
        	Waiter waiter2 = new Waiter(message);
        	
        	Notifier notifier = new Notifier(message);
        	
        	new Thread(waiter1, "waiter1").start();;
        	new Thread(waiter2, "waiter2").start();;
        	new Thread(notifier,"notifier").start();
        	
        	new Thread();
        }
        
    }
    

     

    展开全文
  • JavaFX线程应用

    2013-09-19 10:10:54
    学习javafx,就开始应用。因为需要连接数据库,但连接的时候界面就像死掉了一样,所以考虑使用另一个线程去做数据库连接,但又因为连接完成以后需要更新界面上的元素,所以就不能使用Thread了,这里主要使用到...
  • JavaFX+Jfoenix 学习笔记系列文章的JavaFX+Jfoenix 学习笔记(七)--多线程、延迟加载源码
  • JavaFX是单线程编程,怎么个意思呢?意思就是所有对界面的操作都会交给唯一的线程Application Thread去处理,比如你要修改按钮一的名称,同时又要添加个按钮二,然后还要干点别的,那么不好意思,操作界面的线程只有...
  • 一、课程简介这是『Java学习指南系列』的第20篇教程 ,是Java开发的高级课程,介绍JavaFX的高级技术。JavaFX教程分为两篇:JavaFX入门篇,JavaFX高级篇。本篇课程的主要以实例为主,穿插必要的理论章节。以实际工程...
  • 这是『Java学习指南系列』的第19篇教程 ,是Java开发的高级课程,介绍JavaFX的入门技术。 JavaFX教程分为2篇:JavaFX入门篇 , JavaFX高级篇。 二、主要内容  本篇介绍JavaFX的基本技术,至少包括以下...
  • JavaFX的同步机制

    2013-02-26 15:14:05
    JavaFX的同步 (李佳明 译自http://docs.oracle.com/javafx/2/threads/jfxpub-threads.htm 原文作者... 本文描述了由javafx.concurrent包提供,用于创建多线程程序一些功能。将会学习到如何将长时任务委派到后台执行以
  • 普通使用 Task<Void> task = new Task<Void>() { @Override protected void succeeded() { super.succeeded(); //当call方法里面的操作完成,回调 ... //还可以自定义一些方法,之后可以在call等方...
  • JavaFX+Jfoenix 学习笔记(序)--引言And软件截图 JavaFX+Jfoenix 学习笔记(一)--环境搭建及多款Hello Word演示 JavaFX+Jfoenix 学习笔记(二)--Stage和Scene JavaFX+Jfoenix 学习笔记(三)--TableView数据...
  • javaFX的Timeline学习

    2009-07-08 10:18:51
    Timerline不同于javafx.async.Task, 后者是使用独立线程来支持的, 而前者是执行在EDT(事件派发线程/主线程)中的; javafx中, 所谓动画, 其基本思路是就是一组基于时间的变量, 而这些变量又与程序中的其他部分(如UI中...
  • javafx_JavaFX的未来

    2020-07-10 17:35:57
    此版本将引入一组新的Java API,这意味着开发人员将不再需要学习新的脚本语言来掌握JavaFX。 新的API将允许开发人员利用Java功能(例如注释,多线程和泛型),并允许JavaFX在其他动态语言(...
  • JavaFX 2.0平台是基于Java技术的富客户端平台。它使应用程序开发者更加容易的开发和部署跨平台的富互联网应用(RIA)。JavaFX 2.0文档包含了JavaFX 2.0所提供的功能的概述。 图1描述了JavaFX 2.0平台的架构组件。...
  • JavaFX 2.0平台是基于Java技术的富client平台。它使应用程序开发人员更加easy的开发和部署跨平台的富互联网应用(RIA)。JavaFX 2.0文档包括了JavaFX 2.0所提供的功能的概述。 图1描写叙述了JavaFX 2.0平台的架构...
  • JavaFX的并发性

    2014-12-25 00:03:21
    这章讲述 javafx.concurrent包 提供创建多线程应用程序的功能。
  • 可以通过本文学到的技术将一个靶...JavaFX引入了新的概念:财产绑定(property binding) 被绑定的对象叫靶对象(target object、binding object、binding property),绑定对象叫源对象(source object、bindable ...
  • |____ javaFX线程结构分析 |____ javaFX系列之launcher启动器:两种启动javaFX的方式及launch(args[])参数设置和获取 场景图(Scenen graph) 图形系统(Graphics System) Glass窗体工具包(Glass window ...
1 2 3 4 5 ... 20
收藏数 1,312
精华内容 524
关键字:

javafx线程学习