利用回调函数在线程和主类中传递消息

本文介绍了一个使用回调函数通知主线程线程结束状态的例子。通过在自定义的ThreadDemo类的run方法中完成任务后,调用主类CallbackDigestUserInterface的静态方法receiveDigest来反馈消息。这种方式可以让主线程在等待子线程时进行其他操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一  回调函数

      采用回调函数,让线程通知主程序何时结束,它通过调用主程序中的一个方法来实现。
     (线程就是在该主类中启动的) ,这就称为回调,因为线程在结束的时候,调用其创建者。这样
     主程序就可以在线程运行的时候休息,而不会占用线程的时间。

 二 线程类实现 

      
 1package cn.bupt.thread;
 2
 3import java.io.*;
 4import java.security.DigestInputStream;
 5import java.security.MessageDigest;
 6import java.security.NoSuchAlgorithmException;
 7
 8import cn.bupt.test.CallbackDigestUserInterface;
 9
10public class ThreadDemo implements Runnable{
11
12    private File input ;
13    private byte [] digest ;
14    public ThreadDemo(File input)
15    {
16        this.input = input ;
17    }

18    
19    public byte [] getDigest()
20    {
21        return digest ;
22    }

23    
24    
25    @Override
26    public void run() {
27    
28        try {
29            FileInputStream in = new FileInputStream(input) ;
30            MessageDigest sha = MessageDigest.getInstance("SHA") ;
31            DigestInputStream din = new DigestInputStream(in , sha) ;
32            
33            int b ;
34            
35            while((b =  din.read()) != -1) ;
36            din.close() ;
37            
38            digest = sha.digest() ;
39            
40            CallbackDigestUserInterface.receiveDigest(digest, input.getName()) ;
41            
42        }
 catch (FileNotFoundException e) {
43            // TODO Auto-generated catch block
44            e.printStackTrace();
45        }
 catch (NoSuchAlgorithmException e) {
46            // TODO Auto-generated catch block
47            e.printStackTrace();
48        }
 catch (IOException e) {
49            // TODO Auto-generated catch block
50            e.printStackTrace();
51        }

52        
53        
54        
55        
56    }

57
58     
59    
60}

61



     在上面代码中的第40行,调用了主类中的一个静态函数 ,而实质上这一静态函数是在线程中运行的。
         
    三 主类中的代码 
         
          主类中的main函数实质上只是启动每一个线程,在线程中的静态函数实质上是在thread类中调用

          
 1package cn.bupt.test;
 2
 3import java.io.File;
 4
 5import cn.bupt.thread.ThreadDemo;
 6
 7public class CallbackDigestUserInterface {
 8
 9    public static void receiveDigest(byte [] digest , String name){
10        
11        StringBuffer result = new StringBuffer(name) ;
12        result.append("") ;
13        for(int j = 0 ; j < digest.length ; j++){
14            result.append(digest[j] + " ") ;        
15        }

16        System.out.println("result :" + result) ;
17    }

18    /** *//**
19     * @param args
20     */

21    public static void main(String[] args) {
22        // TODO Auto-generated method stub        
23        for(int i = 0 ; i < args.length ; i++)
24        {
25            File f = new File(args[i]) ;
26            ThreadDemo td = new ThreadDemo(f) ;
27            Thread t = new Thread(td) ;
28            t.start() ;
29        }
        
30    }

31}

32



   四 总结
         回调函数并没有想象中的那么复杂,只是在thread的run方法的结束前,调用主类中定义的方法。
         方法需要synchronized 的限制。


<think>嗯,用户问的是JFrameJava代码之间如何传递变量。这个问题看起来是关于Java Swing的,特别是如何处理JFrame窗体与序之间的数据传递。我需要先回忆一下Swing的基本结构,以及变量在不同之间传递方法。 首先,JFrame是Swing中的一个顶层容器,通常用来创建窗口应用序。代码可能指的是包含main方法,或者是序的入口点。用户可能是在开发一个图形界面应用时,遇到了如何在界面后台逻辑之间传递数据的问题。 接下来,我需要考虑几种常见的变量传递方式。比如,构造函数传参,通过settergetter方法,使用事件监听器,或者更高级的如观察者模式,甚至数据绑定。不过对于刚入门的用户来说,可能更倾向于简单直接的方法。 第一种方法可能是通过构造函数传递创建JFrame实例时,可以通过构造函数将变量传递进去。例如,中有一个变量,创建JFrame子实例时,通过构造函数的参数传递进去。这样JFrame的子就可以保存这个变量并在需要的地方使用。 第二种方法是使用gettersetter方法持有JFrame实例,然后通过调用JFrame的公共方法设置变量。比如,在某个时刻需要更新JFrame中的某个值,就调用frame.setVariable(value),然后在JFrame内部处理这个变量的更新。 第三种情况可能涉及到事件监听,比如按钮点击后需要将用户输入的数据传递。这时候,可以在JFrame中添加监听器,当事件触发时,获取文本框的值,并通过回调方法或者直接调用方法传递数据。 另外,可能需要考虑的是,如果需要访问JFrame中的组件,比如获取文本框的内容,这时候JFrame应该提供公共方法可以获取这些值。或者,在事件处理中直接更新的变量。例如,在按钮的ActionListener中,获取输入并更新的某个字段。 还有可能用户的问题是关于如何从方法启动JFrame,并在创建JFrame实例时传递初始参数。比如,main方法中创建JFrame子对象时,传递参数给构造函数,这样JFrame初始化时就能使用这些变量。 需要举一些例子来说明这些情况。比如,创建JFrame实例,通过构造函数传递一个字符串,然后在JFrame中显示这个字符串。或者,在JFrame中有一个文本框一个按钮,点击按钮后,将文本框的内容传递进行处理。 另外,要注意Swing是单线的,所有对UI的更新都必须在事件分派线中进行,这可能涉及到使用SwingUtilities.invokeLater来确保线安全。不过,变量传递本身可能不涉及多线问题,除非在后台线中修改变量并更新UI。 可能用户遇到的困惑是如何在JFrame的子之间保持变量的同步,或者如何在不同的组件之间传递数据。比如,用户输入的数据需要在多个窗口或之间共享,这时候可能需要更全局的解决方案,比如单例模式或使用共享的数据模型。 总结一下,传递变量的方法要有构造函数传参、setter/getter方法、事件监听与回调、以及使用共享的数据模型。需要根据具体的应用场景选择合适的方法。例如,如果变量在创建JFrame时就已经确定,用构造函数比较合适;如果需要在运行时动态更新,用setter方法或事件监听更合适。 在回答时,应该分步骤说明不同的方法,并给出代码示例,这样用户更容易理解。同时,提醒一些注意事项,比如封装性、线安全等,但可能不需要太深入,避免让初学者感到困惑。</think>在Java Swing中,JFrame(窗口)与(如包含 `main` 方法)之间的变量传递,通常通过以下方式实现。以下是几种常见方法及示例: --- ### 1. **通过构造函数传递变量** 在创建JFrame子实例时,直接通过构造函数传递变量。 ```java // public class Main { public static void main(String[] args) { String data = "Hello from Main!"; MyFrame frame = new MyFrame(data); // 通过构造函数传递 frame.setVisible(true); } } // JFrame子 class MyFrame extends JFrame { private String receivedData; public MyFrame(String data) { receivedData = data; JLabel label = new JLabel(receivedData); add(label); setSize(300, 200); } } ``` --- ### 2. **使用Setter/Getter方法** 通过公共方法动态设置或获取变量值。 ```java // public class Main { public static void main(String[] args) { MyFrame frame = new MyFrame(); frame.setCustomData("Data set by Main"); // 调用setter frame.setVisible(true); } } // JFrame子 class MyFrame extends JFrame { private String customData; public void setCustomData(String data) { this.customData = data; updateUI(); // 更新界面 } private void updateUI() { JLabel label = new JLabel(customData); add(label); setSize(300, 200); } } ``` --- ### 3. **事件监听与回调** 通过按钮点击等事件,将数据从JFrame传递。 ```java // public class Main { public static void main(String[] args) { MyFrame frame = new MyFrame(); frame.setDataListener(data -> { System.out.println("Main收到数据: " + data); }); frame.setVisible(true); } } // JFrame子 class MyFrame extends JFrame { private JTextField textField; public MyFrame() { textField = new JTextField(20); JButton button = new JButton("提交"); button.addActionListener(e -> { if (dataListener != null) { dataListener.onDataSubmitted(textField.getText()); } }); add(textField); add(button); setLayout(new FlowLayout()); setSize(300, 200); } // 定义监听器接口 public interface DataListener { void onDataSubmitted(String data); } private DataListener dataListener; public void setDataListener(DataListener listener) { this.dataListener = listener; } } ``` --- ### 4. **共享数据模型** 使用一个独立的数据,实现多组件共享数据。 ```java // 数据模型 class SharedData { private String value; // Getter & Setter public String getValue() { return value; } public void setValue(String value) { this.value = value; } } // public class Main { public static void main(String[] args) { SharedData data = new SharedData(); MyFrame frame = new MyFrame(data); data.setValue("Main设置的值"); frame.updateDisplay(); // 手动触发界面更新 frame.setVisible(true); } } // JFrame子 class MyFrame extends JFrame { private SharedData sharedData; private JLabel label; public MyFrame(SharedData data) { this.sharedData = data; label = new JLabel(); add(label); setSize(300, 200); } public void updateDisplay() { label.setText(sharedData.getValue()); } } ``` --- ### **关键点总结** - **构造函数传参**:适合初始化时已知的数据。 - **Setter/Getter**:适合动态更新数据。 - **事件监听**:适合用户交互触发的场景(如按钮点击)。 - **共享模型**:适合复杂应用,解耦界面与逻辑。 根据具体需求选择合适的方法,确保数据流向清晰且符合面向对象设计原则。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值