Java 在MQ v6 api中-如何停止MQQueue get()方法?
我正在使用mqv6api类编写一个简单的Java应用程序 现在我可以在while循环中浏览远程队列。此程序作为windows服务运行,必须中断,然后服务停止。首先,我设置waitInterval=MQC.MQWI_UNLIMITED,但MQMessage.get()防止循环中断。然后我将waitInterval设置为5000,并捕获MQRC_NO_MSG_AVAILABLE。这是正常的解决方案还是有更好的解决方案?Java 在MQ v6 api中-如何停止MQQueue get()方法?,java,multithreading,ibm-mq,interrupt,Java,Multithreading,Ibm Mq,Interrupt,我正在使用mqv6api类编写一个简单的Java应用程序 现在我可以在while循环中浏览远程队列。此程序作为windows服务运行,必须中断,然后服务停止。首先,我设置waitInterval=MQC.MQWI_UNLIMITED,但MQMessage.get()防止循环中断。然后我将waitInterval设置为5000,并捕获MQRC_NO_MSG_AVAILABLE。这是正常的解决方案还是有更好的解决方案? 以下是读取循环的代码: public class MessageConsumer
以下是读取循环的代码:
public class MessageConsumer {
private MessageListener ml;
private MQQueue queue;
private Thread sideThread;
static Logger logger = Logger.getLogger(MessageConsumer.class);
private static volatile boolean listening = true;
public MessageConsumer(MQQueue queue) {
this.queue = queue;
}
public void setMessageListener(MessageListener ml) throws MQException {
this.ml = ml;
start();
}
public synchronized void stop() {
this.listening = false;
logger.log(Priority.INFO, "listening = false");
sideThread.interrupt();
logger.log(Priority.INFO, "set sideThread.interrupt()");
}
private void listen() throws MQException {
MQGetMessageOptions getOptions = new MQGetMessageOptions();
getOptions.options = MQC.MQGMO_WAIT + MQC.MQGMO_FAIL_IF_QUIESCING + MQC.MQGMO_LOGICAL_ORDER + MQC.MQGMO_ALL_SEGMENTS_AVAILABLE + MQC.MQGMO_COMPLETE_MSG + MQC.MQGMO_SYNCPOINT;
getOptions.waitInterval = 5000;//MQC.MQWI_UNLIMITED;
logger.log(Priority.INFO, "Start of listening");
int i = 1;
while (listening) {
// try {
System.out.println("Read message");
MQMessage message = new MQMessage();
logger.log(Priority.INFO, "Waiting message: ");
try {
queue.get(message, getOptions);
logger.log(Priority.INFO, "Get message: ");
if (ml != null) {
ml.onMessage(message);
}
} catch (MQException e) {
if (e.reasonCode == e.MQRC_NO_MSG_AVAILABLE) {
System.out.println("no more message available or retrived");
} else {
throw e;
}
}
}
logger.log(Priority.INFO, "End of listening");
}
private void start() throws MQException {
sideThread = new Thread(new Runnable() {
@Override
public void run() {
try {
listen();
} catch (MQException mqex) {
logger.log(Priority.ERROR, "A WebSphere MQ Error occured : Completion Code "
+ mqex.completionCode + " Reason Code "
+ mqex.reasonCode, mqex);
mqex.printStackTrace();
}
}
});
sideThread.start();
try {
sideThread.join();
} catch (InterruptedException ex) {
logger.log(Priority.INFO, "MessageConsumer.start()", ex);
java.util.logging.Logger.getLogger(MessageConsumer.class.getName()).log(Level.SEVERE, null, ex);
}
}
}) 使用5s超时并不是一个很好的方法-我希望你同意这一点,否则你不会问这个问题 答案是使用线程。在调用
get
方法之前,通知线程您正在调用get
。当get完成时,通知它您已完成。您还必须安排在服务停止时通知线程。当线程被告知服务必须停止时,它应该中断线程(因此您的get
)
这里有一个例子。创建其中一个并开始运行。无论何时您要调用get
调用register()
。当get
完成调用deRegister()
时。当服务停止时,呼叫stop()
,所有未完成的get
s将被中断
public class StopWatcher implements Runnable {
// Use a blocking queue to signal the stop - that way we avoid sleeps etc.
BlockingQueue stop = new ArrayBlockingQueue(1);
// All threads that need to be interrupted.
Set<Thread> needInterrupting = new ConcurrentSkipListSet<Thread> ();
@Override
public void run() {
try {
// Block on the stop queue - i.e. wait until stop is called.
stop.take();
} catch (InterruptedException ex) {
// Just ignore it - we need to interrupt everyone anyway whether we have been interrupted or not.
}
// Interrupt everuone who needs it.
for ( Thread t : needInterrupting ) {
t.interrupt();
}
}
// Register for interruption.
public void register () {
needInterrupting.add(Thread.currentThread());
}
// Register for interruption.
public void deRegister () {
needInterrupting.remove(Thread.currentThread());
}
// Stop.
public void stop () {
// Post something in the queue to trigger the stop process.
stop.add(this);
}
}
公共类StopWatcher实现可运行{
//使用阻塞队列发出停止信号-这样我们可以避免睡眠等。
BlockingQueue stop=new ArrayBlockingQueue(1);
//所有需要中断的线程。
Set needInterrupting=new ConcurrentSkipListSet();
@凌驾
公开募捐{
试一试{
//阻塞停止队列-即等待直到调用停止。
停下来;
}捕获(中断异常例外){
//不管有没有被打断,我们都需要打断每个人。
}
//打断任何需要的人。
for(线程t:需要中断){
t、 中断();
}
}
//登记中断。
公共无效注册(){
needInterrupting.add(Thread.currentThread());
}
//登记中断。
公开作废注销人(){
needInterrupting.remove(Thread.currentThread());
}
//停下来。
公众停车场(){
//在队列中发布某些内容以触发停止进程。
停止。添加(此);
}
}
再想一想,如果您已经是多线程的,那么您可能不需要线程就可以完成它
public class StopWatcher {
// All threads that need to be interrupted.
Set<Thread> needInterrupting = new ConcurrentSkipListSet<Thread> ();
// Register for interruption.
public void register () {
needInterrupting.add(Thread.currentThread());
}
// Register for interruption.
public void deRegister () {
needInterrupting.remove(Thread.currentThread());
}
// Stop.
public void stop () {
// Interrupt everuone who needs it.
for ( Thread t : needInterrupting ) {
t.interrupt();
}
needInterrupting.clear();
}
}
公共类秒表{
//所有需要中断的线程。
Set needInterrupting=new ConcurrentSkipListSet();
//登记中断。
公众作废登记册(){
needInterrupting.add(Thread.currentThread());
}
//登记中断。
公开作废注销人(){
needInterrupting.remove(Thread.currentThread());
}
//停下来。
公众停车场(){
//打断任何需要的人。
for(线程t:需要中断){
t、 中断();
}
需要中断;
}
}
商品已经腐化了。我很困惑。我对你的代码有点修改:
package threadUtil;
import java.util.Comparator;
import java.util.Set;
import java.util.concurrent.ConcurrentSkipListSet;
public class StopWatcher2 {
// All threads that need to be interrupted.
// Set<Thread> needInterrupting = new ConcurrentSkipListSet<Thread> ();
Set<Thread> needInterrupting = new ConcurrentSkipListSet<Thread>(new Comparator<Thread>() {
@Override
public int compare(Thread o1, Thread o2) {
Long l1 = o1.getId();
Long l2 = o2.getId();
if (l1.equals(l2)) {
return 0;
} else {
return -1;
}
}
});
// Register for interruption.
public void register() {
needInterrupting.add(Thread.currentThread());
System.out.println("register thread: name=" + Thread.currentThread().getId());
}
// Register for interruption.
public void deRegister() {
needInterrupting.remove(Thread.currentThread());
System.out.println("deRegister thread: name=" + Thread.currentThread().getId());
}
// Stop.
public void stop() {
// Interrupt everuone who needs it.
String name;
long id;
for (Thread t : needInterrupting) {
name = t.getName();
id = t.getId();
t.interrupt();
System.out.println("interrupt thread: name=" + name + ": id= " + id);
}
needInterrupting.clear();
}
}
package-threadUtil;
导入java.util.Comparator;
导入java.util.Set;
导入java.util.concurrent.ConcurrentSkipListSet;
公共类秒表2{
//所有需要中断的线程。
//Set needInterrupting=new ConcurrentSkipListSet();
Set needInterrupting=new ConcurrentSkipListSet(new Comparator(){
@凌驾
公共int比较(线程o1、线程o2){
长l1=o1.getId();
Long l2=o2.getId();
如果(l1等于(l2)){
返回0;
}否则{
返回-1;
}
}
});
//登记中断。
公开作废登记册(){
needInterrupting.add(Thread.currentThread());
System.out.println(“注册线程:name=“+thread.currentThread().getId());
}
//登记中断。
公开作废注销人(){
needInterrupting.remove(Thread.currentThread());
System.out.println(“注销线程:name=“+thread.currentThread().getId());
}
//停下来。
公共停车场(){
//打断任何需要的人。
字符串名;
长id;
for(线程t:需要中断){
name=t.getName();
id=t.getId();
t、 中断();
System.out.println(“中断线程:name=“+name+”:id=“+id”);
}
需要中断;
}
}
并编写一个简单的模型(而不是mqqueue与套接字一起工作-用于建模问题)。所有代码:
package multithreadingportlistener;
import java.io.IOException;
import java.util.Comparator;
import java.util.logging.Level;
import java.util.logging.Logger;
import threadUtil.StopWatcher;
public class MultithreadingPortListener {
private class ThreadComparator extends Thread implements Comparator<Thread> {
public ThreadComparator(Thread t) {
}
@Override
public int compare(Thread o1, Thread o2) {
if (o1.getName().equalsIgnoreCase(o2.getName())) {
return 0;
} else {
return 1;
}
}
}
public static void main(String[] args) {
MultiThreadedServer server = new MultiThreadedServer(9000);
new Thread(server).start();
try {
Thread.sleep(20 * 100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(
"Stopping Server");
server.stop();
}
}
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package multithreadingportlistener;
import java.net.ServerSocket;
import java.net.Socket;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import threadUtil.StopWatcher2;
public class MultiThreadedServer implements Runnable {
protected int serverPort = 8080;
protected ServerSocket serverSocket = null;
protected boolean isStopped = false;
protected Thread runningThread = null;
private StopWatcher2 sw;
public MultiThreadedServer(int port) {
this.serverPort = port;
sw = new StopWatcher2();
}
public void run() {
synchronized (this) {
this.runningThread = Thread.currentThread();
}
openServerSocket();
while (!isStopped()) {
Socket clientSocket = null;
try {
sw.register();
clientSocket = this.serverSocket.accept();
System.out.println("wair accept().");
sw.deRegister();
} catch (IOException e) {
if (isStopped()) {
System.out.println("Server Stopped.");
return;
}
throw new RuntimeException(
"Error accepting client connection", e);
}
new Thread(
new WorkerRunnable(
clientSocket, "Multithreaded Server")).start();
}
System.out.println("Server Stopped.");
}
private synchronized boolean isStopped() {
return this.isStopped;
}
public synchronized void stop() {
this.isStopped = true;
sw.stop(); // special instead this.serverSocket.close() for modelling as mqqueue
}
private void openServerSocket() {
try {
this.serverSocket = new ServerSocket(this.serverPort);
} catch (IOException e) {
throw new RuntimeException("Cannot open port 8080", e);
}
}
}
包多线程PortListener;
导入java.io.IOException;
导入java.util.Comparator;
导入java.util.logging.Level;
导入java.util.logging.Logger;
导入threadUtil.StopWatcher;
公共类多线程PortListener{
私有类ThreadComparator扩展线程实现Comparator{
公共线程比较器(线程t){
}
@凌驾
公共int比较(线程o1、线程o2){
if(o1.getName().equalsIgnoreCase(o2.getName())){
返回0;
}否则{
返回1;
}
}
}
公共静态void main(字符串[]args){
多线程服务器服务器=新的多线程服务器(9000);
新线程(server.start();
试一试{
线程。睡眠(20*100);
}捕捉(中断异常e){
e、 printStackTrace();
}
System.out.println(
“停止服务器”);
server.stop();
}
}
/*
*要更改此模板,请选择工具|模板
*然后在编辑器中打开模板。
*/
包多线程PortListener;
导入java.net.ServerSocket;
导入java.net.Socket;
导入java.io.IOException;
导入java.util.logging.Level;
导入java.util.logging.Logger;
导入threadUtil.StopWatc