Java线程学习

[size=large][b]从线程中取得信息[/b][/size]
[b]轮询 [/b] 主程序无限循环,从子线程取得返回值,直到子线程执行完毕(返回值不为0)
public class ReturnThread extends Thread {
private int time;
private int result;

public ReturnThread(int time) {
this.time = time;
}

public void run() {
try {
TimeUnit.SECONDS.sleep(time);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
result = time;
}

public int getResult() {
return result;
}
}

public class ReturnThreadShell {

public static void main(String[] args) {
Random r = new Random(47);
ReturnThread[] threads = new ReturnThread[5];
for (int i = 0; i < 5; i++) {
int time = r.nextInt(10);
ReturnThread thread = new ReturnThread(time);
threads[i] = thread;
thread.start();
}
for (int i = 0; i < threads.length; i++) {
while (true) {
int rslt = threads[i].getResult();
if (rslt != 0) {
System.out.println("thread " + i + "
is finish. return value is " + rslt);
break;
}
}
}
}
}
//thread 0 is finish. return value is 8
//thread 1 is finish. return value is 5
//thread 2 is finish. return value is 3
//thread 3 is finish. return value is 1
//thread 4 is finish. return value is 1


[b]回调[/b] 子线程执行完成后,调用主线程的方法
public class CallbackThread extends Thread {
private int time;
private CallbackThreadShell callback;

public CallbackThread(int time, CallbackThreadShell callback) {
this.time = time;
this.callback = callback;
}

public void run() {
try {
TimeUnit.SECONDS.sleep(time);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
callback.receiveResult(time, callback.threadId);
}
}

public class CallbackThreadShell {
private int time;
protected int threadId;

public CallbackThreadShell(int time, int threadId) {
this.time = time;
this.threadId = threadId;
}

public void runThread() {
CallbackThread thread = new CallbackThread(time, this);
thread.start();
}

public void receiveResult(int result, int threadId) {
System.out.println("thread " + threadId
+ " is finish. return value is " + result);
}

public static void main(String[] args) {
Random r = new Random(47);
for (int i = 0; i < 5; i++) {
CallbackThreadShell shell = new CallbackThreadShell(r.nextInt(10), i);
shell.runThread();
}
}
}
//thread 3 is finish. return value is 1
//thread 4 is finish. return value is 1
//thread 2 is finish. return value is 3
//thread 1 is finish. return value is 5
//thread 0 is finish. return value is 8


[size=large][b]同步[/b] [/size]
[b]同步块[/b] java无法阻止其他所有线程使用共享资源的方法,他只能防止对同一对象同步的其他线程使用该共享资源
[b]同步方法[/b]

[b]同步的替代方法[/b]
1 使用局部变量代替类变量
2 简单类型的方法参数是安全的,因为java通过值传递不是引用传递参数,对象类型的方法参数,如果是final的,也是线程安全的
3 将非线程安全的类,作为一个线程安全的类的私有字段


[size=large][b]死锁[/b][/size]
防止死锁要避免不必要的线程同步!!


[size=large][b]线程调度[/b][/size]
[b]抢占与协作[/b] 抢占式线程调度器确定线程公平的享用CPU时间,然后暂停此线程,将CPU控制权交给另外的线程。(饥饿问题很难发现)
协作式线程调度器会在CPU控制权交给其他线程前,等待运行中的线程自己暂停。

为了有利于其他线程,一个线程有以下方式可以暂停或指示准备暂停
[b]阻塞[/b] I/O时阻塞、同步其他对象是阻塞。当线程必须停下来,等待他没有的资源,就发生了阻塞。此时线程不会释放任何线程已经拥有的锁。

[b]放弃 [/b] Thread.yield()。线程愿意暂停,让其他同等优先级的线程有机会运行

[b]休眠 [/b] Thread.sleep()。线程不管有没有其他线程准备运行都会暂停
调用休眠线程的interrupt()方法,可以唤醒该线程,这是线程与Thread对象之间的重要区别之一(线程休眠中,仍然可以调用方法与之交互)唤醒会让休眠线程得到一个InterruptedException
一个通过InterruptedException结束线程的例子

public void run(){
while(true){
try{ Thread.sleep(300000);
}catch(InterruptedException e){ break;}}}


[b]连接线程 [/b] Thread.join()。一个线程需要另一个线程的结果,即主线程(调用join()方法的线程)等待被连接的线程(join()方法被调用的线程)结束.

[b]等待一个对象[/b] Object.wait()。等待用于暂停执行,直到一个对象或资源达到某种状态,连接则用于暂停执行,知道一个线程结束。在等待时,他会释放此对象的锁并暂停(但不是他拥有的任何其他对象的锁),直到得到其他线程通知notify()或时间到期、线程被中断interrupt()。
一旦等待线程得到通知,他就试图重新获得所等待对象的锁,如果成功,就继续执行紧接着wait()调用后的语句,如果失败,他就会阻塞与此对象,直到可以得到锁。
while (pool.isEmpty()) {
try {
pool.wait();
// 收到通知时,停止等待,执行之后的内容
// 必须pool.isEmpty(),因为我们不知道处理完成后,pool中是否仍有内容
} catch (InterruptedException ex) {}
}
// 取得一个连接,处理这一项。。。
connection = (Socket) pool.remove(0);

synchronized (pool) {
pool.add(pool.size(), request);
pool.notifyAll();
}

[b]基于优先级的抢占[/b] setPriority()方法

[b]结束[/b] 当run()方法返回时,线程将销毁,其他线程就可以接管CPU。


[size=large][b]线程池[/b][/size]
实现方法
1 第一次创建池时,分配固定数量的线程,当池为空时,所有线程都在等待,当向池添加一项任务时,所有等待的线程都得到通知。当一个线程结束其分配的任务时,它再回到池中等待新任务。
2 将线程本身放在池中,让主程序从池中取出线程,为其分配任务。每个线程结束后返回池中。


一个例子,多线程压缩文件

public class GZipThread extends Thread {

private List pool;
private static int filesCompressed = 0;

public GZipThread(List pool) {
this.pool = pool;
}

private static synchronized void incrementFilesCompressed() {
filesCompressed++;
System.out.println(filesCompressed);
}

public void run() {
while (filesCompressed != GZipAllFiles.getNumberOfFilesToBeCompressed()) {
File input = null;
synchronized (pool) {
while (pool.isEmpty()) {
if (filesCompressed == GZipAllFiles.getNumberOfFilesToBeCompressed()) {
System.out.println("Thread ending");
return;
}
try {
pool.wait();
} catch (InterruptedException ex) {
}
}
input = (File) pool.remove(pool.size() - 1);
incrementFilesCompressed();
}
// don't compress an already compressed file
if (!input.getName().endsWith(".gz")) {
try {
InputStream in = new FileInputStream(input);
in = new BufferedInputStream(in);
File output = new File(input.getParent(), input.getName() + ".gz");
if (!output.exists()) { // Don't overwrite an existing file
OutputStream out = new FileOutputStream(output);
out = new GZIPOutputStream(out);
out = new BufferedOutputStream(out);
int b;
while ((b = in.read()) != -1)
out.write(b);
out.flush();
out.close();
in.close();
}
} catch (IOException ex) {
System.err.println(ex);
}
} // end if
} // end while
} // end run
} // end ZipThread

public class GZipAllFiles {

public final static int THREAD_COUNT = 4;
private static int filesToBeCompressed = -1;

public static void main(String[] args) {
Vector pool = new Vector();
GZipThread[] threads = new GZipThread[THREAD_COUNT];
for (int i = 0; i < threads.length; i++) {
threads[i] = new GZipThread(pool);
threads[i].start();
}
int totalFiles = 0;
for (int i = 0; i < args.length; i++) {
File f = new File(args[i]);
if (f.exists()) {
if (f.isDirectory()) {
File[] files = f.listFiles();
for (int j = 0; j < files.length; j++) {
// 不递归文件夹
if (!files[j].isDirectory()) {
totalFiles++;
synchronized (pool) {
pool.add(0, files[j]);
pool.notifyAll();
}
}
}
} else {
totalFiles++;
synchronized (pool) {
pool.add(0, f);
pool.notifyAll();
}
}
} // end if
} // end for
filesToBeCompressed = totalFiles;
System.out.println("totalFiles " + filesToBeCompressed);
// 让等待线程知道,没有更多的文件会加到池中了
// 如果需要压缩文件很少,有可能线程启动了,但没有需要压缩的文件
for (int i = 0; i < threads.length; i++) {
threads[i].interrupt();
}
}

public static int getNumberOfFilesToBeCompressed() {
return filesToBeCompressed;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
使用 JavaScript 编写的记忆游戏(附源代码)   项目:JavaScript 记忆游戏(附源代码) 记忆检查游戏是一个使用 HTML5、CSS 和 JavaScript 开发的简单项目。这个游戏是关于测试你的短期 记忆技能。玩这个游戏 时,一系列图像会出现在一个盒子形状的区域中 。玩家必须找到两个相同的图像并单击它们以使它们消失。 如何运行游戏? 记忆游戏项目仅包含 HTML、CSS 和 JavaScript。谈到此游戏的功能,用户必须单击两个相同的图像才能使它们消失。 点击卡片或按下键盘键,通过 2 乘 2 旋转来重建鸟儿对,并发现隐藏在下面的图像! 如果翻开的牌面相同(一对),您就赢了,并且该对牌将从游戏中消失! 否则,卡片会自动翻面朝下,您需要重新尝试! 该游戏包含大量的 javascript 以确保游戏正常运行。 如何运行该项目? 要运行此游戏,您不需要任何类型的本地服务器,但需要浏览器。我们建议您使用现代浏览器,如 Google Chrome 和 Mozilla Firefox, 以获得更好、更优化的游戏体验。要玩游戏,首先,通过单击 memorygame-index.html 文件在浏览器中打开游戏。 演示: 该项目为国外大神项目,可以作为毕业设计的项目,也可以作为大作业项目,不用担心代码重复,设计重复等,如果需要对项目进行修改,需要具备一定基础知识。 注意:如果装有360等杀毒软件,可能会出现误报的情况,源码本身并无病毒,使用源码时可以关闭360,或者添加信任。
使用 JavaScript 编写的 Squareshooter 游戏及其源代码   项目:使用 JavaScript 编写的 Squareshooter 游戏(附源代码) 这款游戏是双人游戏。这是一款使用 JavaScript 编写的射击游戏,带有门户和强化道具。在这里,每个玩家都必须控制方形盒子(作为射手)。这款射击游戏的主要目标是射击对手玩家以求生存。当它射击对手时,它会获得一分。 游戏制作 该游戏仅使用 HTML 和 JavaScript 开发。该游戏的 PC 控制也很简单。 对于玩家 1: T:朝你上次动作的方向射击 A:向左移动 D:向右移动 W:向上移动 S:向下移动 对于玩家2: L:朝你上次移动的方向射击 左箭头:向左移动 右箭头:向右移动 向上箭头:向上移动 向下箭头:向下移动 游戏会一直进行,直到您成功射击对手或对手射击您为止。游戏得分显示在顶部。所有游戏功能均由 JavaScript 设置,而布局和其他次要功能则由 HTML 设置。 如何运行该项目? 要运行此项目,您不需要任何类型的本地服务器,但需要浏览器。我们建议您使用现代浏览器,如 Google Chrome 和 Mozilla Firefox。要运行此游戏,首先,通过单击 index.html 文件在浏览器中打开项目。 演示: 该项目为国外大神项目,可以作为毕业设计的项目,也可以作为大作业项目,不用担心代码重复,设计重复等,如果需要对项目进行修改,需要具备一定基础知识。 注意:如果装有360等杀毒软件,可能会出现误报的情况,源码本身并无病毒,使用源码时可以关闭360,或者添加信任。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值