对于在Java7中是invokeAll感兴趣的读者,本文将会是一篇不错的选择,我们将详细介绍的阻塞调用,并为您提供关于"在创建窗口句柄之前,不能在控件上调用Invoke或BeginInvoke"、79
对于在Java 7中是invokeAll感兴趣的读者,本文将会是一篇不错的选择,我们将详细介绍的阻塞调用,并为您提供关于"在创建窗口句柄之前,不能在控件上调用 Invoke 或 BeginInvoke"、79-C# 在创建窗口句柄之前,不能在控件上调用 Invoke 或 BeginInvoke错误的解决办法、c# – 多个Control.BeginInvoke / Invoke调用按顺序执行?、dubbo源码分析之--java.lang.IllegalStateException: urls to invokers error .invokerUrls.size :1, invoker.si的有用信息。
本文目录一览:- 在Java 7中是invokeAll()的阻塞调用(在java7中,下列哪个说法是正确的)
- "在创建窗口句柄之前,不能在控件上调用 Invoke 或 BeginInvoke"
- 79-C# 在创建窗口句柄之前,不能在控件上调用 Invoke 或 BeginInvoke错误的解决办法
- c# – 多个Control.BeginInvoke / Invoke调用按顺序执行?
- dubbo源码分析之--java.lang.IllegalStateException: urls to invokers error .invokerUrls.size :1, invoker.si
在Java 7中是invokeAll()的阻塞调用(在java7中,下列哪个说法是正确的)
ExecutorService executorService = Executors.newSingleThreadExecutor();Set<Callable<String>> callables = new HashSet<Callable<String>>();callables.add(new Callable<String>() { public String call() throws Exception { return "Task 1"; }});callables.add(new Callable<String>() { public String call() throws Exception { return "Task 2"; }});callables.add(new Callable<String>() { public String call() throws Exception { return "Task 3"; }});List<Future<String>> futures = executorService.invokeAll(callables);for(Future<String> future : futures){ System.out.println("future.get = " + future.get());}
对于此代码段。我的问题是“ invokeAll()是否是阻塞调用”?我的意思是,当代码运行到invokeAll()行时,我们是否在此等待所有生成的结果?
答案1
小编典典执行给定的任务,并在所有任务完成时返回保存其状态和结果的期货列表。 Future.isDone()对于返回列表的每个元素为true。
请注意,已完成的任务可能已正常终止,也可能引发异常。如果在进行此操作时修改了给定的集合,则此方法的结果不确定。
期货只能在执行完成时完成,因此,只有在任务执行完毕后才能返回此方法。
它可以引发InterruptedException的情况也表示阻塞动作。
查看invokeAll
in java.util.concurrent.AbstractExecutorService
(注释内联)的实现:
public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks) throws InterruptedException { if (tasks == null) throw new NullPointerException(); ArrayList<Future<T>> futures = new ArrayList<Future<T>>(tasks.size()); boolean done = false; try { for (Callable<T> t : tasks) { RunnableFuture<T> f = newTaskFor(t); futures.add(f); execute(f); } for (int i = 0, size = futures.size(); i < size; i++) { Future<T> f = futures.get(i); if (!f.isDone()) { try { f.get(); // <== *** BLOCKS HERE *** } catch (CancellationException ignore) { } catch (ExecutionException ignore) { } } } done = true; return futures; } finally { if (!done) for (int i = 0, size = futures.size(); i < size; i++) futures.get(i).cancel(true); }}
实际上,在这些情况下,当Javadoc-Specese似乎难以破译时,通常应该看一下参考实现。(请注意,一些实现细节不是规范的一部分。)
"在创建窗口句柄之前,不能在控件上调用 Invoke 或 BeginInvoke"
以前的解决办法(这是网上找的):
“在Window窗体程序开发的时候,如果使用多线程编程,在子线程中访问主线程窗体内的控件,就需要使用控件的Control.Invoke方法或者BeginInvoke方法。但是有时候因为Window执行速度太快,尤其是你写代码的时候在InitializeComponent();完成之前起了一个线程去执行某些操作,涉及到窗体控件的,当你在调用Control.Invoke的时候,就可能出现 “在创建窗口句柄之前,不能在控件上调用 Invoke 或 BeginInvoke”错误。
解决的办法就是让线程等待,直到窗口句柄创建完毕:
//防止在窗口句柄初始化之前就走到下面的代码
while (!this.IsHandleCreated)
{
;
}
this.BeginInvoke(new ProListIndexChangedDelegate(GetProLyric));
//根据不同情况也可以:
if (this.IsHandleCreated)
BeginInvoke(new ProListIndexChangedDelegate(GetProLyric));
”
//--------------------------------------------------------------------
我的程序是这样的:
Form1有Button1、Button2和Button3两个按钮,Button2是动态的new Form2窗体,Form2中注册了Form1中的事件.
Button1的作用是关闭所有new出来的Form2窗体,并且把其资源释放掉(Dispose()).
Button3是让Form2中注册Form1了的事件都发生。
操作:
先点Button2 new出几个Form2的窗体,然后点击Button1释放掉所有的资源,然后再单击Button2 new出几个Form2的窗体,再单击Button3问题就出现了。老是提示"在创建窗口句柄之前,不能在控件上调用 Invoke 或 BeginInvoke"。
查找问题:
再次新建窗体的窗口句柄在Show()之后都通过IsHandleCreated属性检测过了,再调用Invoke()之前都创建了,还是会出错。那问题出在哪里呢?一开始还以为单击Button1没有真正的释放资源,然后我就强制GC了,然后检测不到以前的窗体了,但是还是不行,还是有问题。
然后就想到了“事件”上面来了。是不是事件的原因呀?以前创建的窗体没有注销该事件,把之前所有的窗体都注销该事件,问题就解决了......
https://www.cnblogs.com/hsapphire/archive/2010/10/21/1857421.html
79-C# 在创建窗口句柄之前,不能在控件上调用 Invoke 或 BeginInvoke错误的解决办法
会出现这个错误的可能原因为: 窗体关闭了,但还有线程没执行完,且该线程有在操作窗体的内容:
if (_lik启动任务.IsHandleCreated)
{
_lik启动任务.Invoke(new Action(() =>
{
if (rs.Exists == true)
{
_lik启动任务.Enabled = true;
if (rs.status == ServiceControllerStatus.Running)
{
_lik启动任务.Text = "停止任务(已启动)";
}
else
{
_lik启动任务.Text = "启动任务(未启动)";
}
_lik安装与卸载服务.Text = "卸载服务";
}
else
{
_lik启动任务.Text = "启动任务(服务不存在)";
_lik启动任务.Enabled = false;
_lik安装与卸载服务.Text = "安装服务";
}
}));
}
若没有加:_lik启动任务.IsHandleCreated 这个if判断,直接执行,就会报错。
_lik启动任务 是窗体的link控件。
c# – 多个Control.BeginInvoke / Invoke调用按顺序执行?
我有以下情况:
> UI线程被阻止
> WCF线程调用Control.BeginInvoke
> WCF线程调用Control.Invoke(或者可能是BeginInvoke再次)
> UI线程被解除封锁
> ??
步骤1-4的执行顺序保证是按照显示的顺序(技术上,订单不能保证是这样,但是如果订单如图所示,我的问题只有相关).
我的问题是在步骤2中的BeginInvoke调用之前是否有可能在步骤3中调用Invoke / BeginInvoke调用?
另外,请不要评论阻止UI线程.
解决方法
UI线程实际上是一个消息泵,它具有单个消息队列,只有一个线程消耗它,所以保证工作项将按照它们排队的顺序执行.
它与Delegate.BeginInvoke有关,执行顺序可能不是顺序的.
dubbo源码分析之--java.lang.IllegalStateException: urls to invokers error .invokerUrls.size :1, invoker.si
最近在生产环境和预发环境经常出现java.lang.IllegalStateException: urls to invokers error .invokerUrls.size :1, invoker.size :0,这一类的error错误,具体错误信息如下
java.lang.IllegalStateException: urls to invokers error .invokerUrls.size :1, invoker.size :0. urls :[dubbo://192.168.137.13:20881/com.alibaba.dubbo.demo.DemoService?anyhost=true&application=dubbodemoprovider&dubbo=2.5.3.6&interface=com.alibaba.dubbo.demo.DemoService&methods=complexInvoke,complex,Timeout,complexObject,complexUser,sayHello2,$$sayHelloTest,complexArray2,hessianTest,sayHello,HelloWorld,hessianMapTest,complexArray,hessianSerialable,ThrowException,mockDate&pid=3094&revision=2.5.3.8-SNAPSHOT&side=provider×tamp=1493780202580]
at com.alibaba.dubbo.registry.integration.RegistryDirectory.refreshInvoker(RegistryDirectory.java:229) [dubbo-2.5.3.9.jar:2.5.3.9]
at com.alibaba.dubbo.registry.integration.RegistryDirectory.notify(RegistryDirectory.java:195) [dubbo-2.5.3.9.jar:2.5.3.9]
at com.alibaba.dubbo.registry.support.AbstractRegistry.notify(AbstractRegistry.java:449) [dubbo-2.5.3.9.jar:2.5.3.9]
at com.alibaba.dubbo.registry.support.FailbackRegistry.doNotify(FailbackRegistry.java:273) [dubbo-2.5.3.9.jar:2.5.3.9]
at com.alibaba.dubbo.registry.support.FailbackRegistry.notify(FailbackRegistry.java:259) [dubbo-2.5.3.9.jar:2.5.3.9]
at com.alibaba.dubbo.registry.zookeeper.ZookeeperRegistry.access$400(ZookeeperRegistry.java:45) [dubbo-2.5.3.9.jar:2.5.3.9]
at com.alibaba.dubbo.registry.zookeeper.ZookeeperRegistry$3.childChanged(ZookeeperRegistry.java:163) [dubbo-2.5.3.9.jar:2.5.3.9]
at com.alibaba.dubbo.remoting.zookeeper.zkclient.ZkclientZookeeperClient$2.handleChildChange(ZkclientZookeeperClient.java:82) [dubbo-2.5.3.9.jar:2.5.3.9]
at org.I0Itec.zkclient.ZkClient$7.run(ZkClient.java:568) [zkclient-0.1.jar:na]
at org.I0Itec.zkclient.ZkEventThread.run(ZkEventThread.java:71) [zkclient-0.1.jar:na]
首先出现该类型错误,并不影响正常调用,dubbo中有保护机制,当所有的的provider都被disable后,会保留最后一个被disable的provider,提供正常的服务。具体的实现代码如下RegistryDirectory类中的如下方法
private void refreshInvoker(List<URL> invokerUrls){ if (invokerUrls != null && invokerUrls.size() == 1 && invokerUrls.get(0) != null && Constants.EMPTY_PROTOCOL.equals(invokerUrls.get(0).getProtocol())) { this.forbidden = true; // 禁止访问 this.methodInvokerMap = null; // 置空列表 destroyAllInvokers(); // 关闭所有Invoker } else { this.forbidden = false; // 允许访问 Map<String, Invoker<T>> oldUrlInvokerMap = this.urlInvokerMap; // local reference if (invokerUrls.size() == 0 && this.cachedInvokerUrls != null){ invokerUrls.addAll(this.cachedInvokerUrls); } else { this.cachedInvokerUrls = new HashSet<URL>(); this.cachedInvokerUrls.addAll(invokerUrls);//缓存invokerUrls列表,便于交叉对比 } if (invokerUrls.size() ==0 ){ return; } Map<String, Invoker<T>> newUrlInvokerMap = toInvokers(invokerUrls) ;// 将URL列表转成Invoker列表 Map<String, List<Invoker<T>>> newMethodInvokerMap = toMethodInvokers(newUrlInvokerMap); // 换方法名映射Invoker列表 // state change //如果计算错误,则不进行处理. //这里是抛出具体错误的地方,当newUrlInvokerMap都为空时,这里会打印出ERROR日志 if (newUrlInvokerMap == null || newUrlInvokerMap.size() == 0 ){ logger.error(new IllegalStateException("urls to invokers error .invokerUrls.size :"+invokerUrls.size() + ", invoker.size :0. urls :"+invokerUrls.toString())); return ; } this.methodInvokerMap = multiGroup ? toMergeMethodInvokerMap(newMethodInvokerMap) : newMethodInvokerMap; this.urlInvokerMap = newUrlInvokerMap; try{ destroyUnusedInvokers(oldUrlInvokerMap,newUrlInvokerMap); // 关闭未使用的Invoker }catch (Exception e) { logger.warn("destroyUnusedInvokers error. ", e); } } }
具体是在进行灰度发布时,会先进行disable,会通过zookeeper通知到客户端,进行连接销毁,因为disable操作是单个进行,所以当操作到最后一个时,如果发现没有可用提供者,则会打印error日志,保留最后一个如下是AbstractRegistry类中的通知
protected void notify(URL url, NotifyListener listener, List<URL> urls) { if (url == null) { throw new IllegalArgumentException("notify url == null"); } if (listener == null) { throw new IllegalArgumentException("notify listener == null"); } if ((urls == null || urls.size() == 0) && ! Constants.ANY_VALUE.equals(url.getServiceInterface())) { logger.warn("Ignore empty notify urls for subscribe url " + url); return; } if (logger.isDebugEnabled()) { logger.debug("Notify urls for subscribe url " + url + ", urls: " + urls); } Map<String, List<URL>> result = new HashMap<String, List<URL>>(); for (URL u : urls) { if (UrlUtils.isMatch(url, u)) { String category = u.getParameter(Constants.CATEGORY_KEY, Constants.DEFAULT_CATEGORY); List<URL> categoryList = result.get(category); if (categoryList == null) { categoryList = new ArrayList<URL>(); result.put(category, categoryList); } categoryList.add(u); } } if (result.size() == 0) { return; } Map<String, List<URL>> categoryNotified = notified.get(url); if (categoryNotified == null) { notified.putIfAbsent(url, new ConcurrentHashMap<String, List<URL>>()); categoryNotified = notified.get(url); } for (Map.Entry<String, List<URL>> entry : result.entrySet()) { String category = entry.getKey(); List<URL> categoryList = entry.getValue(); categoryNotified.put(category, categoryList); saveProperties(url); listener.notify(categoryList); } }
RegistryDirectory类中的通知
public synchronized void notify(List<URL> urls) { List<URL> invokerUrls = new ArrayList<URL>(); List<URL> routerUrls = new ArrayList<URL>(); List<URL> configuratorUrls = new ArrayList<URL>(); for (URL url : urls) { String protocol = url.getProtocol(); String category = url.getParameter(Constants.CATEGORY_KEY, Constants.DEFAULT_CATEGORY); if (Constants.ROUTERS_CATEGORY.equals(category) || Constants.ROUTE_PROTOCOL.equals(protocol)) { routerUrls.add(url); } else if (Constants.CONFIGURATORS_CATEGORY.equals(category) || Constants.OVERRIDE_PROTOCOL.equals(protocol)) { configuratorUrls.add(url); } else if (Constants.PROVIDERS_CATEGORY.equals(category)) { invokerUrls.add(url); } else { logger.warn("Unsupported category " + category + " in notified url: " + url + " from registry " + getUrl().getAddress() + " to consumer " + NetUtils.getLocalHost()); } } // configurators if (configuratorUrls != null && configuratorUrls.size() >0 ){ this.configurators = toConfigurators(configuratorUrls); } // routers if (routerUrls != null && routerUrls.size() >0 ){ List<Router> routers = toRouters(routerUrls); if(routers != null){ // null - do nothing setRouters(routers); } } List<Configurator> localConfigurators = this.configurators; // local reference // 合并override参数 this.overrideDirectoryUrl = directoryUrl; if (localConfigurators != null && localConfigurators.size() > 0) { for (Configurator configurator : localConfigurators) { this.overrideDirectoryUrl = configurator.configure(overrideDirectoryUrl); } } // providers refreshInvoker(invokerUrls); }
下面的连接销毁的方法是DubboInvoker中
//destroyUnusedInvokers这个方法中真正去销毁时会去调用该方法 public void destroy() { //防止client被关闭多次.在connect per jvm的情况下,client.close方法会调用计数器-1,当计数器小于等于0的情况下,才真正关闭 if (super.isDestroyed()){ return ; } else { //dubbo check ,避免多次关闭 destroyLock.lock(); try{ if (super.isDestroyed()){ return ; } super.destroy(); if (invokers != null){ invokers.remove(this); } for (ExchangeClient client : clients) { try { client.close(); } catch (Throwable t) { logger.warn(t.getMessage(), t); } } }finally { destroyLock.unlock(); } } }
关于在Java 7中是invokeAll和的阻塞调用的问题我们已经讲解完毕,感谢您的阅读,如果还想了解更多关于"在创建窗口句柄之前,不能在控件上调用 Invoke 或 BeginInvoke"、79-C# 在创建窗口句柄之前,不能在控件上调用 Invoke 或 BeginInvoke错误的解决办法、c# – 多个Control.BeginInvoke / Invoke调用按顺序执行?、dubbo源码分析之--java.lang.IllegalStateException: urls to invokers error .invokerUrls.size :1, invoker.si等相关内容,可以在本站寻找。
本文标签: