- 欢迎光临 ^ V ^
文章目录




public static void main(String[] args) {
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println("好耶 ^ v ^");
}
}
},1000);
System.out.println("不好耶 T . T");
}

TimerTask实现了Runnable

而在Timer的schedule方法内部,则将这个线程保存起来,定时后执行~

原因是:
public class Test {
public static void main(String[] args) {
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
System.out.println("星期一好耶 ^ v ^");
}
},1000);
timer.schedule(new TimerTask() {
@Override
public void run() {
System.out.println("星期二好耶 ^ v ^");
}
},2000);
timer.schedule(new TimerTask() {
@Override
public void run() {
System.out.println("星期三好耶 ^ v ^");
}
},3000);
timer.schedule(new TimerTask() {
@Override
public void run() {
System.out.println("星期四好耶 ^ v ^");
}
},4000);
timer.schedule(new TimerTask() {
@Override
public void run() {
System.out.println("星期五好耶 ^ v ^");
}
},5000);
System.out.println("今天不好耶 T . T");
}
}


应用场景特别多
而这个任务等待,不应该是无期限的
定时器可以强制终止请求:浏览器内部都有一个定时器,发送请求后,定时器就开始定时;若在规定时间内,响应数据没有返回,就会强制终止请求

这个方法一般在任务的run方法中调用,确定是否及时
是不是触动你的DNA了?
即,定时器底层就是一个阻塞优先级队列! ===> PriorityBlockingQueue
class MyTask {
public Runnable runnable;
public long time;
}
public class MyTimer {
private PriorityBlockingQueue<MyTask> tasks = new PriorityBlockingQueue<>();
}
阻塞优先级队列中的元素应该有如下两个信息:

System.currentTimeMillis()class MyTask {
public Runnable runnable;
public long time;
//绝对时间戳~
//方便判断~
//这个不是定时时间
public MyTask(Runnable runnable, long delay) {
this.runnable = runnable;
this.time = delay + System.currentTimeMillis();
}
}
public void schedule(Runnable runnable, long delay) {
MyTask myTask = new MyTask(runnable, delay);
tasks.put(myTask);
}
public MyTimer() {
Thread t = new Thread(() -> {
try {
MyTask myTask = tasks.take();
long nowTime = System.currentTimeMillis();
if(myTask.time <= nowTime) {
//启动
}else {
//不能启动
}
} catch (InterruptedException e) {
e.printStackTrace();
}
});
}
}

对于1. 比较规则:
只需要让MyTask实现比较接口
当然也可以传比较器~(lambda表达式)

两种方式都OK~
左减右大于0
如果代表此对象大于该对象代表升序排列 ===> 小根堆
如果代表此对象小于该对象代表降序排列 ===> 大根堆
对于2. “没有等待”以及“盲目等待”

wait等待,唤醒起来比较方便安全
“盲目等待” 代表,这里放回去后,计算器又会判断是否可启动
那么我们只需要在schedule时唤醒一下,让他才判断一次就行了~
大大减少判断次数!

public void schedule(Runnable runnable, long delay) {
MyTask myTask = new MyTask(runnable, delay);
tasks.put(myTask);
synchronized (locker) {
locker.notify();
}
}
private Object locker = new Object();
public MyTimer() {
Thread t = new Thread(() -> {
while(true) {
synchronized (locker) {
try {
MyTask myTask = tasks.take();
long nowTime = System.currentTimeMillis();
if(myTask.time <= nowTime) {
myTask.runnable.run();
}else {
tasks.put(myTask);
locker.wait(myTask.time - nowTime);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
t.start();
}

用MyTimer替换之前的Timer
TimeTask也可替换为Runnable,不过没关系,向上转型~
public static void main(String[] args) {
MyTimer timer = new MyTimer();
timer.schedule(new TimerTask() {
@Override
public void run() {
System.out.println("星期一好耶 ^ v ^");
}
},1000);
timer.schedule(new TimerTask() {
@Override
public void run() {
System.out.println("星期二好耶 ^ v ^");
}
},2000);
timer.schedule(new TimerTask() {
@Override
public void run() {
System.out.println("星期三好耶 ^ v ^");
}
},3000);
timer.schedule(new TimerTask() {
@Override
public void run() {
System.out.println("星期四好耶 ^ v ^");
}
},4000);
timer.schedule(new TimerTask() {
@Override
public void run() {
System.out.println("星期五好耶 ^ v ^");
}
},5000);
System.out.println("今天不好耶 T . T");
}


public static void main(String[] args) {
MyTimer timer = new MyTimer();
timer.schedule(new TimerTask() {
@Override
public void run() {
System.out.println("星期一好耶 ^ v ^");
try {
Thread.sleep(5000);
System.out.println("已过去五秒");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},1000);
timer.schedule(new TimerTask() {
@Override
public void run() {
System.out.println("星期二好耶 ^ v ^");
}
},2000);
timer.schedule(new TimerTask() {
@Override
public void run() {
System.out.println("星期三好耶 ^ v ^");
}
},3000);
timer.schedule(new TimerTask() {
@Override
public void run() {
System.out.println("星期四好耶 ^ v ^");
}
},4000);
timer.schedule(new TimerTask() {
@Override
public void run() {
System.out.println("星期五好耶 ^ v ^");
}
},5000);
System.out.println("今天不好耶 T . T");
}
}




注意:
问:wait的同步锁的位置不同,结果会怎么样?



提高效率还能提高轻量化线程“协程”,Java标准库还不支持
而线程池是一个重要的途径~

需要内核支持,才能运行的应用程序~
即,内核给那么多人服务,那么就不一定及时
举个栗子:


也就是说,我们在申请线程时
内核态申请 ==> 内核要顾及进程管理和其他管理与驱动~

用户态去拿 ==> 只需要在进程管理这个单项里去拿线程~

当然,线程的诞生,还是要内核态申请
Java标准库实现了一个接口,ExecutorService,在进程中服务线程执行~
但是这个接口不是通过new子类对象去实例化的,而是用一个静态方法去实例化~

“工厂”
而工厂模式其实就是,把一个类/接口的构造方法,交给一个“工厂类”去定义
Executors工厂:


你也可以自己“开个厂”
public class A {
int a1;
int a2;
int a3;
int a4;
int a5;
int a6;
}

public static A createA1(int a) {
//匿名内部类优先捕获全局性质变量,这里在代码块内,a1就为全局性变量~
return new A() {
{
this.a1 = a;
}
};
}
public static A createA2(int a) {
return new A() {
{
this.a2 = a;
}
};
}
public static A createA3(int a) {
return new A() {
{
this.a3 = a;
}
};
}
public static A createA4(int a) {
return new A() {
{
this.a4 = a;
}
};
}
public static A createA5(int a) {
return new A() {
{
this.a5 = a;
}
};
}
public static A createA6(int a) {
return new A() {
{
this.a6 = a;
}
};
}
}

class CreateComparatorA {
public static Comparator<A> createA1() {
return ((o1, o2) -> {
return o1.a1 - o2.a1;
});
}
public static Comparator<A> createA2() {
return ((o1, o2) -> {
return o1.a2 - o2.a2;
});
}
public static Comparator<A> createA3() {
return ((o1, o2) -> {
return o1.a3 - o2.a3;
});
}
public static Comparator<A> createA4() {
return ((o1, o2) -> {
return o1.a4 - o2.a4;
});
}
public static Comparator<A> createA5() {
return ((o1, o2) -> {
return o1.a5 - o2.a5;
});
}
public static Comparator<A> createA6() {
return ((o1, o2) -> {
return o1.a6 - o2.a6;
});
}
}

public class A {
int a1;
int a2;
int a3;
int a4;
int a5;
int a6;
//参数列表相同无法特定构造特定成员~
@Override
public String toString() {
return "A{" +
"a1=" + a1 +
", a2=" + a2 +
", a3=" + a3 +
", a4=" + a4 +
", a5=" + a5 +
", a6=" + a6 +
'}' + '\n';
}
public static void main(String[] args) {
PriorityQueue<A> queue1 = new PriorityQueue<>(CreateComparatorA.createA1());
PriorityQueue<A> queue2 = new PriorityQueue<>(CreateComparatorA.createA2());
PriorityQueue<A> queue3 = new PriorityQueue<>(CreateComparatorA.createA3());
PriorityQueue<A> queue4 = new PriorityQueue<>(CreateComparatorA.createA4());
PriorityQueue<A> queue5 = new PriorityQueue<>(CreateComparatorA.createA5());
PriorityQueue<A> queue6 = new PriorityQueue<>(CreateComparatorA.createA6());
queue1.offer(createA.createA1(2));
queue1.offer(createA.createA1(1));
queue1.offer(createA.createA1(4));
queue1.offer(createA.createA1(3));
queue1.offer(createA.createA1(5));
System.out.println(queue1);
}
}

当然,工厂当然不只可以生产构造方法:


最重点的一个:


public static void main(String[] args) {
ExecutorService pool = Executors.newFixedThreadPool(10);
pool.submit(() -> {
System.out.println("好耶 ^ v ^ ");
});
}
下面是Java的官方文档的内容:


线程池会在任务少的空闲期,根据这些参数进行线程调整,把一些临时线程给销毁了~
keepAliveTime 为临时线程存活时间~
unit ==> 时间单位

public class MyThreadPool {
private BlockingQueue<Runnable> pool = new LinkedBlockingQueue<>();
public void submit(Runnable runnable) throws InterruptedException {
pool.put(runnable);
}
//实现固定线程数的线程池
//不是容量,是确确实实的线程数
public MyThreadPool(int number) {
for (int i = 0; i < number; i++) {
Thread thread = new Thread(() -> {
Runnable runnable = null;
try {
while(true) {
runnable = pool.take();
runnable.run();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
});
thread.start();
}
}
}
我们的简单实现,不涉及2.4.3的属性~
注意:这里的线程数,是工作人数,定量

public static void main(String[] args) throws InterruptedException {
MyThreadPool myThreadPool = new MyThreadPool(10);
for (int i = 1; i <= 1000; i++) {
int id = i; //线程id,变量捕获~
myThreadPool.submit(() -> {
System.out.println("好耶^ v ^ " + id);
});
}

——
线程池中如何体现,“用户态拿”:

注意:
至于线程池固定线程数,设置为多少合适?
cpu密集型,主要做一些计算工作,要在cpu上运行~
IO密集型,主要等待一些IO操作(读写硬盘/读写网卡),不怎么吃cpu
而实际情况不会这么极端,所以这个线程数一定是要看实际情况的
文章到此结束!谢谢观看 !
可以叫我 小马,我可能写的不好或者有错误,但是一起加油鸭🦆!多线程初阶已经结束~ 后续会出线程进阶的博客!
敬请期待吧~
我正在尝试测试是否存在表单。我是Rails新手。我的new.html.erb_spec.rb文件的内容是:require'spec_helper'describe"messages/new.html.erb"doit"shouldrendertheform"dorender'/messages/new.html.erb'reponse.shouldhave_form_putting_to(@message)with_submit_buttonendendView本身,new.html.erb,有代码:当我运行rspec时,它失败了:1)messages/new.html.erbshou
我在从html页面生成PDF时遇到问题。我正在使用PDFkit。在安装它的过程中,我注意到我需要wkhtmltopdf。所以我也安装了它。我做了PDFkit的文档所说的一切......现在我在尝试加载PDF时遇到了这个错误。这里是错误:commandfailed:"/usr/local/bin/wkhtmltopdf""--margin-right""0.75in""--page-size""Letter""--margin-top""0.75in""--margin-bottom""0.75in""--encoding""UTF-8""--margin-left""0.75in""-
我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t
在railstutorial中,作者为什么选择使用这个(代码list10.25):http://ruby.railstutorial.org/chapters/updating-showing-and-deleting-usersnamespace:dbdodesc"Filldatabasewithsampledata"task:populate=>:environmentdoRake::Task['db:reset'].invokeUser.create!(:name=>"ExampleUser",:email=>"example@railstutorial.org",:passwo
我有一个对象has_many应呈现为xml的子对象。这不是问题。我的问题是我创建了一个Hash包含此数据,就像解析器需要它一样。但是rails自动将整个文件包含在.........我需要摆脱type="array"和我该如何处理?我没有在文档中找到任何内容。 最佳答案 我遇到了同样的问题;这是我的XML:我在用这个:entries.to_xml将散列数据转换为XML,但这会将条目的数据包装到中所以我修改了:entries.to_xml(root:"Contacts")但这仍然将转换后的XML包装在“联系人”中,将我的XML代码修改为
为了将Cucumber用于命令行脚本,我按照提供的说明安装了arubagem。它在我的Gemfile中,我可以验证是否安装了正确的版本并且我已经包含了require'aruba/cucumber'在'features/env.rb'中为了确保它能正常工作,我写了以下场景:@announceScenario:Testingcucumber/arubaGivenablankslateThentheoutputfrom"ls-la"shouldcontain"drw"假设事情应该失败。它确实失败了,但失败的原因是错误的:@announceScenario:Testingcucumber/ar
我在我的项目中添加了一个系统来重置用户密码并通过电子邮件将密码发送给他,以防他忘记密码。昨天它运行良好(当我实现它时)。当我今天尝试启动服务器时,出现以下错误。=>BootingWEBrick=>Rails3.2.1applicationstartingindevelopmentonhttp://0.0.0.0:3000=>Callwith-dtodetach=>Ctrl-CtoshutdownserverExiting/Users/vinayshenoy/.rvm/gems/ruby-1.9.3-p0/gems/actionmailer-3.2.1/lib/action_mailer
我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server
在MRIRuby中我可以这样做:deftransferinternal_server=self.init_serverpid=forkdointernal_server.runend#Maketheserverprocessrunindependently.Process.detach(pid)internal_client=self.init_client#Dootherstuffwithconnectingtointernal_server...internal_client.post('somedata')ensure#KillserverProcess.kill('KILL',
我已经从我的命令行中获得了一切,所以我可以运行rubymyfile并且它可以正常工作。但是当我尝试从sublime中运行它时,我得到了undefinedmethod`require_relative'formain:Object有人知道我的sublime设置中缺少什么吗?我正在使用OSX并安装了rvm。 最佳答案 或者,您可以只使用“require”,它应该可以正常工作。我认为“require_relative”仅适用于ruby1.9+ 关于ruby-主要:Objectwhenrun