java中的多线程
多线程:
为啥需要多线程:充分利用cpu,单一任务若等待输入,cpu将处在空闲时间。
注:在某个类中可以产生该类的实例,相当于在某个类产生“另外一个类”的实例,要注意是否溢出。循环和异常要正确放置,循环放置在异常里面,否则的话,尽管捕获异常程序还是会执行。
为什么多线程会需要同步:有时线程顺序执行,否则会导致数据不一致。
synchronized关键字,一次只允许一个线程进入临界区。synchronized只是一个内置锁的加锁机制,当某个方法加上synchronized关键字后,就表明要获得该内置锁才能执行,并不能阻止其他线程访问不需要获得该内置锁的方法。
对java语言程序设计中生产者和消费者的疑问和思考:看过王道论坛中的操作系统还是可以理解的,它基本上和王道论坛是一样的,信号量上锁操作。在多线程还是要注意一些细节:条件wait会使线程挂起,处在等待状态,条件signal会唤醒等待线程,但是并不意味着等待线程立即执行,多线程是不可控的,意味着你无法决定哪一个线程将会运行,但是可以决定不管哪一个线程运行,以及怎么运行都可以实现你的目标,也就是说尽管一个你不希望的线程运行了,但是当他执行代码时,条件不对,它就不会执行之后的代码。
java中的condition用于协调线程之间的交互。主动,直接让线程挂起,或者唤醒一个等待的线程,线程中调用sleep方法相当于定时器,两者不是同一个架构上的问题。
信号量有专门的类:Semaphore 信号量用来限制对一个共享资源的访问的线程数。比如多个生产者进行并发,这也相当于某个线程多次运行。
简单的资源排序可以避免死锁。
java中的Fork/Join并行编程:注意是并行,抽象类ForkJoinTask定义一个用于异步执行任务。ForkJoinPool执行并行任务。
网络:
书中结合了javafx用于可视化网络操作:
网络相关操作是通过socket来建立连接的,传输的文件是用文件流来通信的,懂得网络和可视化,那么可以用来开发一些有趣的小程序。书中一个3*3的井字小游戏就是借助网络实现的小游戏。
基本思想其实还是模拟两个人下棋,然后多了一个服务器做中间商。服务器和客户端通信通过六个状态信息控制,玩家一进入房间,玩家二进入房间,继续游戏,平局,玩家一胜利,玩家二胜利。
服务器发送给客户端信息都是以状态信息起始的,然后是一些其他信息。客户端发送给服务器的信息很简单,就是井字棋的行列位置两个信息。不过客户端严格遵守发送信息,等待信息过程,其中客户端有个操作很亮眼,用一个int型waiting量,来保证发送信息的线程的方法一定执行在绘制图象的线程之后。看完这些代码感觉对于整体的代码设计,方法定义,类间关系熟悉好的话,这样写代码简直是一种阅读享受,因为有时不需要看完全部代码,相当于就有个整体把握。
2019.3.2
继续对多线程进行更新,今天学习了volatile关键字的作用。目前感觉学习java多线程的时候,最好把关于jvm的内存模型看一遍,它跟多线程相关性很大。先讲解一下volatile关键字,它让变量变得“线程可见”,每个线程都有自己的私有工作区,所以有一些共享变量他会拷贝到自己工作区,多线程的情况下,有时候尽管某个线程更新了这个共享变量,但是其他线程还是选择过时的自己工作区的拷贝量,这就造成问题,无法保证数据最新,volatile会强制线程取得最新值,现在直接上代码,flag用volatile关键字修饰与不修饰会发生什么。
package chapter30;
public class Test {
public static void main(String[] args) {
ThreadDemo td = new ThreadDemo();
new Thread(td).start();
while(true) {
if (ThreadDemo.flag) {
System.out.println("--------------");
break;
}
}
}
}
class ThreadDemo implements Runnable {
public static boolean flag = false;
@Override
public void run() {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
flag = true;
System.out.println("flag = " + isFlag());
}
public boolean isFlag() {
return flag;
}
}
注:代码源自https://www.cnblogs.com/ccfdod/p/6392343.html。