java exchanger用在什么场景
发布时间:2025-05-20 21:24:32 发布人:远客网络
一、java exchanger用在什么场景
1、Exchanger是在两个任务之间交换对象的栅栏。当两个任务进入栅栏时,它们各自拥有一个对象,当它们离开时,它们都拥有对方的对象。Exchanger的典型应用场景是:一个任务在创建对象,而这些对象的生产代价很高,另一个任务在消费这些对象。通过这种方式,可以有更多的对象在被创建的同时被消费。
2、为了演示Exchanger类,我们将创建生产者和消费者任务。ExchangerProducer和ExchangerConsumer使用一个List<Fat>作为要求交换的对象,它们都包含一个用于这个List<Fat>的Exchanger。当你调用Exchanger.exchange()方法时,它将阻塞直至对方任务调用它自己的exchange()方法,那时,这两个exchange()方法将同时完成,而List<Fat>被交换:
3、import java.util.concurrent.CopyOnWriteArrayList;
4、import java.util.concurrent.Exchanger;
5、import java.util.concurrent.ExecutorService;
6、import java.util.concurrent.Executors;
7、import java.util.concurrent.TimeUnit;
8、class ExchangerProducer implements Runnable{
9、private List<Fat> holder;
10、private Exchanger<List<Fat>> exchanger;
11、public ExchangerProducer(Exchanger<List<Fat>> exchanger, List<Fat> holder){
12、for(int i= 0;i< ExchangerDemo.size; i++){
13、holder= exchanger.exchange(holder);
14、} catch(InterruptedException e){
15、System.out.println("Producer stopped.");
16、class ExchangerConsumer implements Runnable{
17、private List<Fat> holder;
18、private Exchanger<List<Fat>> exchanger;
19、public ExchangerConsumer(Exchanger<List<Fat>> exchanger, List<Fat> holder){
20、holder= exchanger.exchange(holder);
21、//在循环内删除元素,这对于CopyOnWriteArrayList是没有问题的
22、System.out.println("Exchanged count="+ num);
23、} catch(InterruptedException e){
24、System.out.println("Consumer stopped. Final value:"+ value);
25、public static void main(String[] args) throws Exception{
26、ExecutorService exec= Executors.newCachedThreadPool();
27、List<Fat> producerList= new CopyOnWriteArrayList<>();
28、List<Fat> consumerList= new CopyOnWriteArrayList<>();
29、Exchanger<List<Fat>> exchanger= new Exchanger<>();
30、exec.execute(new ExchangerProducer(exchanger, producerList));
31、exec.execute(new ExchangerConsumer(exchanger, consumerList));
32、TimeUnit.SECONDS.sleep(delay);
33、private static int counter= 1;
34、private final int id= counter++;
35、for(int i= 1; i<10000; i++){
36、d+=(Math.PI+ Math.E)/(double)i;
37、public void print(){System.out.println(this);}
38、public String toString(){return"Fat id="+ id;}
39、Consumer stopped. Final value: Fat id=88300
40、在main()中,创建了用于两个任务的单一的Exchanger,以及两个用于互换的CopyOnWriteArrayList。这个特定的List变体允许列表在被遍历的时候调用remove()方法,而不会抛出ConcurrentModifiedException异常。ExchangerProducer将填充这个List,然后将这个满列表跟ExchangerConsumer的空列表交换。交换之后,ExchangerProducer可以继续的生产Fat对象,而ExchangerConsumer则开始使用满列表中的对象。因为有了Exchanger,填充一个列表和消费另一个列表便同时发生了。
二、《RabbitMQ系列》之RabbitMQ的4种Exchange
1、大家好,本文将介绍RabbitMQ中的4种Exchange:direct、topic、fanout、headers。RabbitMQ拥有4种Exchange,它们是direct、topic、fanout、headers,还有默认的direct Exchange。在实际应用中,direct、topic、fanout是使用最频繁的类型。接下来,我们将通过代码示例,详细介绍这4种Exchange的使用方法与应用场景。
2、Direct Exchange基于routing key与队列的绑定。生产者发送的消息根据指定的routing key,被路由到一个或多个队列。如果交换机绑定了多个队列,则每条消息都会被路由到每个队列中。
3、@EnableRabbit注解用于开启基于注解的RabbitMQ配置。
4、convertAndSend方法用于向RabbitMQ发送消息,其中第一个参数"directExchange"指定交换机名称,第二个参数"rk.001"为routing key,第三个参数为消息内容。
5、@RabbitListener注解用于指定消息消费方法,参数queues指定监听的队列,bindings用于指定与队列的绑定关系。
6、Topic Exchange类似于Direct Exchange,但使用模式匹配的routing key。routing key可以包含通配符,如`*.orange.*`或`lazy.#`,其中`*`代表一个单词,`#`代表多个单词。
7、生产者发送消息时,指定不同的routing key;消费者监听多个队列,通过模式匹配的routing key消费消息。
8、Fanout Exchange不使用routing key,将消息路由到所有与其绑定的队列。与Direct Exchange类似,绑定了Fanout Exchange的队列都会接收到全量消息。
9、生产者无需指定routing key,直接发送消息到Fanout Exchange;消费者监听Fanout Exchange,接收全量消息。
10、Headers Exchange根据消息的头部信息进行路由。配置时需指定x-match参数,用于控制匹配规则。
11、生产者发送消息时指定头部信息;消费者监听队列,通过头部信息匹配消费消息。
12、-**Direct Exchange**:适用于业务数据直接传输并消费的场景,如不同业务模块间的消息交互。
13、-**Topic Exchange**:适用于涉及分类或标记的新闻更新,以及后台任务处理。
14、-**Fanout Exchange**:适用于广播消息的场景,如群聊功能、多人在线游戏更新等。
15、-**Headers Exchange**:适用于routing key复杂且需要灵活匹配的场景。
16、以上就是RabbitMQ中4种Exchange的介绍与使用方法。通过灵活运用这些Exchange,可以实现高效、灵活的消息处理流程。如有疑问或需要进一步讨论,欢迎在评论区留言交流。我是@明人只说暗话,感谢阅读!
三、如何使用Java发送qq邮件
首先,邮件的发送方要开启POP3和SMTP服务--即发送qq邮件的账号要开启POP3和SMTP服务
5.找到:POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV服务—点击开启
7.稍等一会,很得到一个授权码!–注意:这个一定要记住,一会用到
import javax.mail.MessagingException;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMessage.RecipientType;
public static void main(String[] args) throws AddressException, MessagingException{
Properties properties= new Properties();
properties.put("mail.transport.protocol","smtp");//连接协议
properties.put("mail.smtp.host","smtp.qq.com");//主机名
properties.put("mail.smtp.port", 465);//端口号
properties.put("mail.smtp.auth","true");
properties.put("mail.smtp.ssl.enable","true");//设置是否使用ssl安全连接---一般都使用
properties.put("mail.debug","true");//设置是否显示debug信息 true会在控制台显示相关信息
Session session= Session.getInstance(properties);
Message message= new MimeMessage(session);
message.setFrom(new InternetAddress("123456789@qq.com"));
//设置收件人地址 message.setRecipients( RecipientType.TO, new InternetAddress[]{ new InternetAddress("987654321@qq.com")});
message.setSubject("这是第一封Java邮件");
message.setText("内容为:这是第一封java发送来的邮件。");
Transport transport= session.getTransport();
transport.connect("123456789@qq.com","vvctybgbvvophjcj");//密码为刚才得到的授权码
//发送邮件 transport.sendMessage(message, message.getAllRecipients());
下面是我收到邮件的截图,当然我把源码中的邮件地址都是修改了,不是真实的,你们测试的时候,可以修改能你们自己的邮箱。最后,祝你也能成功,如果有什么问题,可以一起讨论!
得到的授权码一定要保存好,程序中要使用