javaretry
㈠ java怎样实现ping的功能...
可以用InetAddress的isReachable方法:
import java.net.InetAddress;
public class MainTest {
public static void main(String[] args) {
try {
int timeOut = 3000;
byte[] ip = new byte[] { (byte) 192, (byte) 168, (byte) 100, (byte) 151 };
int retry = 4;
InetAddress address = InetAddress.getByAddress(ip);
for (int i = 0; i < retry; i++) {
if (address.isReachable(timeOut)) {
System.out.println(i + " OK");
} else {
System.out.println(i + " LOSS");
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
㈡ java中用try如果catch到异常,怎么把这个异常处理掉让程序继续运行
需要先将Scanner内的输入清楚,不然就重复读取了。简单调用Scanner的next()方法就可以了
测试已通过
package;
importjava.util.Scanner;
publicclassRetry{
privateintmyInt;
privateScannermyScanner=newScanner(System.in);
publicintgetInt(){
try{
System.out.println("请输入法整数");
this.myInt=this.myScanner.nextInt();
}catch(Exceptione){
System.out.println("输入错误,请输入正确的数值!!!");
this.myScanner.next();
this.getInt();
}
returnthis.myInt;
}
publicstaticvoidmain(String[]args){
Retryretry=newRetry();
System.out.println(retry.getInt());
}
}
㈢ 用java连接mongodb3报错,不知道问题在哪
在对超过百万条记录的集合进行聚合操作。 DBObject match=(DBObject)JSON.parse("{$match:{logType:{'$in':[5,9]}}}"); DBObject group=(DBObject)JSON.parse("{$group:{'_id':'$domainUrl','count':{'$sum':1}}}"); AggregationOutput output = logCollection.aggregate(match,group); 偶尔会发生Read timed out 异常。 com.mongodb.MongoException$Network: Read operation to server /192.168.10.202:27017 failed on database adLogTable at com.mongodb.DBTCPConnector.innerCall(DBTCPConnector.java:253) at com.mongodb.DB.command(DB.java:261) at com.mongodb.DB.command(DB.java:243) ... Caused by: java.net.SocketTimeoutException: Read timed out at java.net.SocketInputStream.socketRead0(Native Method) at java.net.SocketInputStream.read(SocketInputStream.java:152) 通过多次测试,发现执行一次聚合平均时间为5s,超过5s时就会报错! 然后查看MongoDB的配置信息: socket-timeout="5000" //5s socket-timeout的默认配置为0,也就是没有限制。 没有超时限制,系统出了问题也不容易发现,应该根据实际情况,给出合理的超时时间。 通过多次测试发现最长执行时间为6秒,就把超时时间设置成了10000。 socket-timeout="10000" //10s 注意:MongoDB在与Spring整合时,如果要配置多个MongDB源,只会启用最后一个<mongo:options>配置。 应该把参数配置信息存储在properties文件中。 <mongo:mongo host="${mongodb.ip}" id="mongo202" port="${mongodb.port}"> <mongo:options connections-per-host="200" threads-allowed-to-block-for-connection-multiplier="100" connect-timeout="1000" max-wait-time="1000" auto-connect-retry="true" socket-keep-alive="true" socket-timeout="10000" slave-ok="true" write-number="1" write-timeout="0" write-fsync="true" /> </mongo:mongo> 通过Java API获取配置参数 DBCollection logCollection = mongoTemplate.getCollection(collName); MongoOptions mongoOptions = logCollection.getDB().getMongo().getMongoOptions(); System.out.println(mongoOptions.getSocketTimeout()); 最后一点: ConnectionTimeOut和SocketTimeOut的区别: 一次完整的请求包括三个阶段: 建立连接 数据传输 断开连接 如果与服务器(这里指数据库)请求建立连接的时间超过ConnectionTimeOut,就会抛 ConnectionTimeOutException,即服务器连接超时,没有在规定的时间内建立连接。 如果与服务器连接成功,就开始数据传输了。 如果服务器处理数据用时过长,超过了SocketTimeOut,就会抛出SocketTimeOutExceptin,即服务器响应超时,服务器没有在规定的时间内返回给客户端数据
㈣ Java开发中 global.properties 文件的作用是什么
一个配置文件而已,文件本身的类型和名字没什么特别的,重要的是文件内容。
从文件名来看,文件里的内容应该是这个java应用的全局的一些配置/资源/属性。
properties这种类型的文件采用键值对的形式存放信息,一行就是一条信息,比如:
#numberofretry
Num_Rery=5
上面这条配置中,第一行是说明,properties文件以#开头的是注释;第二行等号左右分别是键和值,键的大小写随意,可包含数字和下划线。
java代码中获取这个键对应的值使用java.util.ResourceBundle,如:
Stringredisurl=ResourceBundle.getBundle("global").getString("Num_Rery");
再多举一个实际应用的例子,比如一个java应用要对另外一个url地址发起请求,这个地址可以写在java代码中,但是有时候为了便于集中管理/阅读,那么我们考虑把她放到一个properties文件中,键是URL_Call,值就是这个url地址,在要使用的地方,用上面的那行java代码获取到就行了。
打完收工~~~~
㈤ java 代码运行之后出现以下错误,到底神马意思呢
第一步:通过”cd“命令切换到java类的存放路径;
第二步:重新确认java类中的代码编写是否正确;
第三步:输入”javac 类名.java“,回车,执行运行,如果不报错说明编译正常,如果报错,根据错误修改java类代码即可。
第四步:输入”java 类名“进行文件运行即可。
㈥ java中 我通过jdbc插入数据进入mysql数据库,为什么会报错啊,一般是1000多条以后就报错了,求大神解释!!
你的tomcat是6.0.18以后的版本么?6.0.18版本以后的tomcat有一个防内存泄露机制,它会强行把jdbc连接给注销掉。如果是,建议换低版本的tomcat
㈦ JAVA中 retry关键用来作甚
这不是关键字 就是标志符 指出下面语句从哪里开始执行 你代码里面有continue retry; 也就是说下面从 retry: 这里继续执行
㈧ 怎样用Java实现网站数据采集.txt
可以使用HttpClient读取网页的内容
整个过程分为六步
创建 HttpClient 的实例
2. 创建某种连接方法的实例,在这里是 GetMethod。在 GetMethod 的构造函数中传入待连接的地址
3. 调用第一步中创建好的实例的 execute 方法来执行第二步中创建好的 method 实例
4. 读 response
5. 释放连接。无论执行方法是否成功,都必须释放连接
6. 对得到后的内容进行处理
实现如下:
import java.io.IOException;
import org.apache.commons.httpclient.*;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.params.HttpMethodParams;
public class HttpClientTest...{
public static void main(String[] args) {
//构造HttpClient的实例
HttpClient httpClient = new HttpClient();
//创建GET方法的实例
GetMethod getMethod = new GetMethod("http://www.crazyjava.org");
//使用系统提供的默认的恢复策略
getMethod.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,
new DefaultHttpMethodRetryHandler());
try {
//执行getMethod
int statusCode = httpClient.executeMethod(getMethod);
if (statusCode != HttpStatus.SC_OK) {
System.err.println("Method failed: "
+ getMethod.getStatusLine());
}
//读取内容
byte[] responseBody = getMethod.getResponseBoy();
//处理内容
System.out.println(new String(responseBody));
} catch (HttpException e) {
//发生异常,可能是协议不对或者返回的内容有问题
System.out.println("Please check your provided http address!");
e.printStackTrace();
} catch (IOException e) {
//发生网络异常
e.printStackTrace();
} finally {
//释放连接
getMethod.releaseConnection();
}
}
}
这样得到的是页面的源代码,再进行处理
㈨ Java线程池中的核心线程是如何被重复利用的
Java线程池中的核心线程是如何被重复利用的?
引言
在Java开发中,经常需要创建线程去执行一些任务,实现起来也非常方便,但如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程就会大大降低系统的效率,因为频繁创建线程和销毁线程需要时间。此时,我们很自然会想到使用线程池来解决这个问题。
使用线程池的好处:
降低资源消耗。java中所有的池化技术都有一个好处,就是通过复用池中的对象,降低系统资源消耗。设想一下如果我们有n多个子任务需要执行,如果我们为每个子任务都创建一个执行线程,而创建线程的过程是需要一定的系统消耗的,最后肯定会拖慢整个系统的处理速度。而通过线程池我们可以做到复用线程,任务有多个,但执行任务的线程可以通过线程池来复用,这样减少了创建线程的开销,系统资源利用率得到了提升。
降低管理线程的难度。多线程环境下对线程的管理是最容易出现问题的,而线程池通过框架为我们降低了管理线程的难度。我们不用再去担心何时该销毁线程,如何最大限度的避免多线程的资源竞争。这些事情线程池都帮我们代劳了。
提升任务处理速度。线程池中长期驻留了一定数量的活线程,当任务需要执行时,我们不必先去创建线程,线程池会自己选择利用现有的活线程来处理任务。
- // 获取运行状态
- private static int runStateOf(int c) { return c & ~CAPACITY; }
- // 获取活动线程数
- private static int workerCountOf(int c) { return c & CAPACITY; }123456
- public void execute(Runnable command) {
- if (command == null)
- throw new NullPointerException();
- int c = ctl.get();
- if (workerCountOf(c) < corePoolSize) {
- if (addWorker(command, true))
- return;
- c = ctl.get();
- }
- if (isRunning(c) && workQueue.offer(command)) {
- int recheck = ctl.get();
- if (! isRunning(recheck) && remove(command))
- reject(command);
- else if (workerCountOf(recheck) == 0)
- addWorker(null, false);
- }
- else if (!addWorker(command, false))
- reject(command);
- }
- // 为分析而简化后的代码
- public void execute(Runnable command) {
- int c = ctl.get();
- if (workerCountOf(c) < corePoolSize) {
- // 如果当前活动线程数小于corePoolSize,则新建一个线程放入线程池中,并把任务添加到该线程中
- if (addWorker(command, true))
- return;
- c = ctl.get();
- }
- // 如果当前活动线程数大于等于corePoolSize,则尝试将任务放入缓存队列
- if (workQueue.offer(command)) {
- int recheck = ctl.get();
- if (workerCountOf(recheck) == 0)
- addWorker(null, false);
- }else {
- // 缓存已满,新建一个线程放入线程池,并把任务添加到该线程中(此时新建的线程相当于非核心线程)
- addWorker(command, false)
- }
- }22
如果 当前活动线程数 < 指定的核心线程数,则创建并启动一个线程来执行新提交的任务(此时新建的线程相当于核心线程);
如果 当前活动线程数 >= 指定的核心线程数,且缓存队列未满,则将任务添加到缓存队列中;
如果 当前活动线程数 >= 指定的核心线程数,且缓存队列已满,则创建并启动一个线程来执行新提交的任务(此时新建的线程相当于非核心线程);
- private boolean addWorker(Runnable firstTask, boolean core) {
- retry:
- for (;;) {
- int c = ctl.get();
- int rs = runStateOf(c);
- // Check if queue empty only if necessary.
- if (rs >= SHUTDOWN &&
- ! (rs == SHUTDOWN &&
- firstTask == null &&
- ! workQueue.isEmpty()))
- return false;
- for (;;) {
- int wc = workerCountOf(c);
- if (wc >= CAPACITY ||
- wc >= (core ? corePoolSize : maximumPoolSize))
- return false;
- if ((c))
- break retry;
- c = ctl.get(); // Re-read ctl
- if (runStateOf(c) != rs)
- continue retry;
- // else CAS failed e to workerCount change; retry inner loop
- }
- }
- boolean workerStarted = false;
- boolean workerAdded = false;
- Worker w = null;
- try {
- w = new Worker(firstTask);
- final Thread t = w.thread;
- if (t != null) {
- final ReentrantLock mainLock = this.mainLock;
- mainLock.lock();
- try {
- // Recheck while holding lock.
- // Back out on ThreadFactory failure or if
- // shut down before lock acquired.
- int rs = runStateOf(ctl.get());
- if (rs < SHUTDOWN ||
- (rs == SHUTDOWN && firstTask == null)) {
- if (t.isAlive()) // precheck that t is startable
- throw new IllegalThreadStateException();
- workers.add(w);
- int s = workers.size();
- if (s > largestPoolSize)
- largestPoolSize = s;
- workerAdded = true;
- }
- } finally {
- mainLock.unlock();
- }
- if (workerAdded) {
- t.start();
- workerStarted = true;
- }
- }
- } finally {
- if (! workerStarted)
- addWorkerFailed(w);
- }
- return workerStarted;
- }
- // 为分析而简化后的代码
- private boolean addWorker(Runnable firstTask, boolean core) {
- int wc = workerCountOf(c);
- if (wc >= (core ? corePoolSize : maximumPoolSize))
- // 如果当前活动线程数 >= 指定的核心线程数,不创建核心线程
- // 如果当前活动线程数 >= 指定的最大线程数,不创建非核心线程
- return false;
- boolean workerStarted = false;
- boolean workerAdded = false;
- Worker w = null;
- try {
- // 新建一个Worker,将要执行的任务作为参数传进去
- w = new Worker(firstTask);
- final Thread t = w.thread;
- if (t != null) {
- workers.add(w);
- workerAdded = true;
- if (workerAdded) {
- // 启动刚刚新建的那个worker持有的线程,等下要看看这个线程做了啥
- t.start();
- workerStarted = true;
- }
- }
- } finally {
- if (! workerStarted)
- addWorkerFailed(w);
- }
- return workerStarted;
- }2223242526272829303132
- private final class Worker
- extends AbstractQueuedSynchronizer
- implements Runnable{
- // ....
- }
- Worker(Runnable firstTask) {
- setState(-1); // inhibit interrupts until runWorker
- this.firstTask = firstTask;
- this.thread = getThreadFactory().newThread(this);
- }123456789101112
- public void run() {
- runWorker(this);
- }
- final void runWorker(Worker w) {
- Thread wt = Thread.currentThread();
- Runnable task = w.firstTask;
- w.firstTask = null;
- w.unlock(); // allow interrupts
- boolean completedAbruptly = true;
- try {
- while (task != null || (task = getTask()) != null) {
- w.lock();
- // If pool is stopping, ensure thread is interrupted;
- // if not, ensure thread is not interrupted. This
- // requires a recheck in second case to deal with
- // shutdownNow race while clearing interrupt
- if ((runStateAtLeast(ctl.get(), STOP) ||
- (Thread.interrupted() &&
- runStateAtLeast(ctl.get(), STOP))) &&
- !wt.isInterrupted())
- wt.interrupt();
- try {
- beforeExecute(wt, task);
- Throwable thrown = null;
- try {
- task.run();
- } catch (RuntimeException x) {
- thrown = x; throw x;
- } catch (Error x) {
- thrown = x; throw x;
- } catch (Throwable x) {
- thrown = x; throw new Error(x);
- } finally {
- afterExecute(task, thrown);
- }
- } finally {
- task = null;
- w.completedTasks++;
- w.unlock();
- }
- }
- completedAbruptly = false;
- } finally {
- processWorkerExit(w, completedAbruptly);
- }
- }04142434445464748
- // 为分析而简化后的代码
- final void runWorker(Worker w) {
- Runnable task = w.firstTask;
- w.firstTask = null;
- while (task != null || (task = getTask()) != null) {
- try {
- task.run();
- } finally {
- task = null;
- }
- }
- }12345678910111213
- private Runnable getTask() {
- boolean timedOut = false; // Did the last poll() time out?
- for (;;) {
- int c = ctl.get();
- int rs = runStateOf(c);
- // Check if queue empty only if necessary.
- if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
- decrementWorkerCount();
- return null;
- }
- int wc = workerCountOf(c);
- // Are workers subject to culling?
- boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;
- if ((wc > maximumPoolSize || (timed && timedOut))
- && (wc > 1 || workQueue.isEmpty())) {
- if ((c))
- return null;
- continue;
- }
- try {
- Runnable r = timed ?
- workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
- workQueue.take();
- if (r != null)
- return r;
- timedOut = true;
- } catch (InterruptedException retry) {
- timedOut = false;
- }
- }
- }
- // 为分析而简化后的代码
- private Runnable getTask() {
- boolean timedOut = false;
- for (;;) {
- int c = ctl.get();
- int wc = workerCountOf(c);
- // timed变量用于判断是否需要进行超时控制。
- // allowCoreThreadTimeOut默认是false,也就是核心线程不允许进行超时;
- // wc > corePoolSize,表示当前线程池中的线程数量大于核心线程数量;
- // 对于超过核心线程数量的这些线程,需要进行超时控制
- boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;
- if (timed && timedOut) {
- // 如果需要进行超时控制,且上次从缓存队列中获取任务时发生了超时,那么尝试将workerCount减1,即当前活动线程数减1,
- // 如果减1成功,则返回null,这就意味着runWorker()方法中的while循环会被退出,其对应的线程就要销毁了,也就是线程池中少了一个线程了
- if ((c))
- return null;
- continue;
- }
- try {
- Runnable r = timed ?
- workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
- workQueue.take();
- // 注意workQueue中的poll()方法与take()方法的区别
- //poll方式取任务的特点是从缓存队列中取任务,最长等待keepAliveTime的时长,取不到返回null
- //take方式取任务的特点是从缓存队列中取任务,若队列为空,则进入阻塞状态,直到能取出对象为止
- if (r != null)
- return r;
- timedOut = true;
- } catch (InterruptedException retry) {
- timedOut = false;
- }
- }
- }39
如果当前活动线程数大于核心线程数,当去缓存队列中取任务的时候,如果缓存队列中没任务了,则等待keepAliveTime的时长,此时还没任务就返回null,这就意味着runWorker()方法中的while循环会被退出,其对应的线程就要销毁了,也就是线程池中少了一个线程了。因此只要线程池中的线程数大于核心线程数就会这样一个一个地销毁这些多余的线程。
如果当前活动线程数小于等于核心线程数,同样也是去缓存队列中取任务,但当缓存队列中没任务了,就会进入阻塞状态,直到能取出任务为止,因此这个线程是处于阻塞状态的,并不会因为缓存队列中没有任务了而被销毁。这样就保证了线程池有N个线程是活的,可以随时处理任务,从而达到重复利用的目的。
当有新任务来的时候,先看看当前的线程数有没有超过核心线程数,如果没超过就直接新建一个线程来执行新的任务,如果超过了就看看缓存队列有没有满,没满就将新任务放进缓存队列中,满了就新建一个线程来执行新的任务,如果线程池中的线程数已经达到了指定的最大线程数了,那就根据相应的策略拒绝任务。
当缓存队列中的任务都执行完了的时候,线程池中的线程数如果大于核心线程数,就销毁多出来的线程,直到线程池中的线程数等于核心线程数。此时这些线程就不会被销毁了,它们一直处于阻塞状态,等待新的任务到来。
很显然,线程池一个很显着的特征就是“长期驻留了一定数量的活线程”,避免了频繁创建线程和销毁线程的开销,那么它是如何做到的呢?我们知道一个线程只要执行完了run()方法内的代码,这个线程的使命就完成了,等待它的就是销毁。既然这是个“活线程”,自然是不能很快就销毁的。为了搞清楚这个“活线程”是如何工作的,下面通过追踪源码来看看能不能解开这个疑问。
分析方法
在分析源码之前先来思考一下要怎么去分析,源码往往是比较复杂的,如果知识储备不够丰厚,很有可能会读不下去,或者读岔了。一般来讲要时刻紧跟着自己的目标来看代码,跟目标关系不大的代码可以不理会它,一些异常的处理也可以暂不理会,先看正常的流程。就我们现在要分析的源码而言,目标就是看看线程是如何被复用的。那么对于线程池的状态的管理以及非正常状态下的处理代码就可以不理会,具体来讲,在ThreadPollExcutor类中,有一个字段private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));是对线程池的运行状态和线程池中有效线程的数量进行控制的, 它包含两部分信息: 线程池的运行状态 (runState) 和线程池内有效线程的数量 (workerCount),还有几个对ctl进行计算的方法:
以上两个方法在源码中经常用到,结合我们的目标,对运行状态的一些判断及处理可以不用去管,而对当前活动线程数要加以关注等等。
下面将遵循这些原则来分析源码。
解惑
当我们要向线程池添加一个任务时是调用ThreadPollExcutor对象的execute(Runnable command)方法来完成的,所以先来看看ThreadPollExcutor类中的execute(Runnable command)方法的源码:
按照我们在分析方法中提到的一些原则,去掉一些相关性不强的代码,看看核心代码是怎样的。
这样一看,逻辑应该清晰很多了。
接下来看addWorker(Runnable firstTask, boolean core)方法
同样,我们也来简化一下:
看到这里,我们大概能猜测到,addWorker方法的功能就是新建一个线程并启动这个线程,要执行的任务应该就是在这个线程中执行。为了证实我们的这种猜测需要再来看看Worker这个类。
从上面的Worker类的声明可以看到,它实现了Runnable接口,以及从它的构造方法中可以知道待执行的任务赋值给了它的变量firstTask,并以它自己为参数新建了一个线程赋值给它的变量thread,那么运行这个线程的时候其实就是执行Worker的run()方法,来看一下这个方法:
在run()方法中只调了一下 runWorker(this) 方法,再来简化一下这个 runWorker() 方法
很明显,runWorker()方法里面执行了我们新建Worker对象时传进去的待执行的任务,到这里为止貌似这个worker的run()方法就执行完了,既然执行完了那么这个线程也就没用了,只有等待虚拟机销毁了。那么回顾一下我们的目标:Java线程池中的核心线程是如何被重复利用的?好像并没有重复利用啊,新建一个线程,执行一个任务,然后就结束了,销毁了。没什么特别的啊,难道有什么地方漏掉了,被忽略了?再仔细看一下runWorker()方法的代码,有一个while循环,当执行完firstTask后task==null了,那么就会执行判断条件(task = getTask()) != null,我们假设这个条件成立的话,那么这个线程就不止只执行一个任务了,可以执行多个任务了,也就实现了重复利用了。答案呼之欲出了,接着看getTask()方法
老规矩,简化一下代码来看:
从以上代码可以看出,getTask()的作用是
小结
通过以上的分析,应该算是比较清楚地解答了“线程池中的核心线程是如何被重复利用的”这个问题,同时也对线程池的实现机制有了更进一步的理解:
注意:
本文所说的“核心线程”、“非核心线程”是一个虚拟的概念,是为了方便描述而虚拟出来的概念,在代码中并没有哪个线程被标记为“核心线程”或“非核心线程”,所有线程都是一样的,只是当线程池中的线程多于指定的核心线程数量时,会将多出来的线程销毁掉,池中只保留指定个数的线程。那些被销毁的线程是随机的,可能是第一个创建的线程,也可能是最后一个创建的线程,或其它时候创建的线程。一开始我以为会有一些线程被标记为“核心线程”,而其它的则是“非核心线程”,在销毁多余线程的时候只销毁那些“非核心线程”,而“核心线程”不被销毁。这种理解是错误的。
另外还有一个重要的接口 BlockingQueue 值得去了解,它定义了一些入队出队同步操作的方法,还可以阻塞,作用很大。