项目经历整理

This commit is contained in:
yinkanglong_lab
2021-04-06 23:30:37 +08:00
parent b845347c66
commit 30f583d779
54 changed files with 3246 additions and 0 deletions

View File

@@ -0,0 +1,117 @@
## 新的事件监听机制
-----
* 之前是定义一个组件对象(事件源),队组建对象绑定一个监听器对象,在监听器对象中有监听同一事件不同动作的函数,函数内部对事件进行处理。从监听器的角度对事件和动作进行处理。
* 现在是直接将静态事件绑定到事件源上通过process函数运行运行事件发生时的处理方式。而且这些静态事件是已经存在于awtEvent类中的。
```
package EventHandle;
import java.awt.*;
import java.awt.event.ComponentEvent;
import java.awt.event.MouseEvent;
import java.awt.event.WindowEvent;
/**
* @author 宙斯
* 准确的说这并不是先前的事件监听机制吧。它不存在指明的监听器。
* 应该更像一种组件自带的事件匹配功能。
* 具体步骤:
* 打开某一类型的事件匹配功能。
* 使用process函数运行某个事件
* 当事件发生时通过事件的ID匹配具体的动作。
* 匹配后设置相应的处理方式。
*/
public class baseEvent extends Frame{
private int x = 0,y = 0,flag = 0;
private Image img;
private int dx = 0,dy = 0;
public static void main(String[] args) {
baseEvent bE = new baseEvent();
}
public baseEvent(){
super();
setSize(500,500);
this.setVisible(true);
Toolkit tk = Toolkit.getDefaultToolkit();
img = tk.getImage("first.png");
//相当于添加了对Component事件的监听器似乎监听器类在底层已经直接绑定。
enableEvents(AWTEvent.COMPONENT_EVENT_MASK);
enableEvents(AWTEvent.WINDOW_EVENT_MASK);
enableEvents(AWTEvent.MOUSE_EVENT_MASK);
repaint();
}
//直接调用底层的事件处理函数
public void processComponentEvent(ComponentEvent e){
if(e.getID() == ComponentEvent.COMPONENT_MOVED){
System.out.println(e.getSource());
System.out.println(e.getID());
}
}
public void processWindowEvent(WindowEvent e){
if(e.getID() == WindowEvent.WINDOW_CLOSING){
System.exit(0);
}
}
/*
public void processMouseEvent(MouseEvent e){
if(e.getID() == MouseEvent.MOUSE_PRESSED){
System.out.println("pressed");
if((e.getX()>= x)&&(e.getX()<=x+100)&&(e.getY()>=y)&&(e.getY()<=y+100)){
flag = 1;
System.out.println(e.getX()+"..."+e.getY());
}
}
if((e.getID()==MouseEvent.MOUSE_RELEASED)&&(flag == 1)){
x = e.getX();
y = e.getY();
repaint();
flag = 0;
}
}
*/
public void processMouseEvent(MouseEvent e){
if(e.getID() == MouseEvent.MOUSE_PRESSED){
System.out.println("pressed");
if((e.getX()>= x)&&(e.getX()<=x+100)&&(e.getY()>=y)&&(e.getY()<=y+100)){
dx = e.getX()-x;
dy = e.getY()-y;
flag = 1;
System.out.println(e.getX()+"..."+e.getY());
}
}
if(e.getID()== MouseEvent.MOUSE_MOVED&&flag ==1){
x = e.getX()-dx;
y = e.getY()-dy;
System.out.println(e.getX()+"..."+e.getY());
repaint();
}
if((e.getID()==MouseEvent.MOUSE_RELEASED)&&(flag == 1)){
flag = 0;
}
}
public void paint(Graphics g){
g.drawImage(img, x, y,100,100, this);
}
}
```

View File

@@ -0,0 +1,84 @@
# 画图的标准步骤
------
package painting;
import java.awt.Frame;
import java.awt.Graphics;
/**
* 画图过程的整体框架.
* 继承了Frame类能够使用相关的框体数据。
* 实现了Rnnable接口本类能够作为一个线程被执行。
* @author 宙斯
*
*/
public class framePaint extends Frame implements Runnable{
public static void main(String [] args){
framePaint workStart = new framePaint();
}
/**
* 无参构造函数.
* 设置了窗体的基本属性。
* 创建了与本类相关的线程并且执行。
* 也就是说,这个类的对象在创建的时候,就已经执行了相关的画图代码,并且产生了一个看见的图形对象。
* 而且这个绘制的过程,会作为一个普通的线程被执行。
*/
public framePaint(){
super("framePaint");
setSize(350,350);
setVisible(true);
new Thread(this).start();
}
/**
* 实现多线程的方法.
* run方法时Runnable线程的主要方法当线程开始是执行这个方法所以画图方法在这个线程方法中被调用
* 这个方法相当于画图过程的总方法。
* @see java.lang.Runnable#run()
*/
public void run(){
repaint();
}
/**
* 实现画图的过程.
* 主要的画图方法在调用画图对象的repaint方法时这个方法被自动加载。
* @see java.awt.Window#paint(java.awt.Graphics)
*/
public void paint(Graphics g){
}
}
# Graphics类中的主要方法
-----
> 能绘制的图形:
> String 字符串
> Line 直线
> Rect 长方形
> Oval 椭圆形
> Arc 弧线
> Polygon 多边形
>
* draw系列
绘制线条图形
* fill系列
绘制平面图形,用前景色填充内容物
* clearRect()
清除指定区域内的图形
* clipRect()
截取制定区域内的图形
* copyArea()
赋值制定区域内的图形到指定区域
* get/setColor/Font
设置颜色字体等
* setClip()
截取制定形状内的图形

View File

@@ -0,0 +1,5 @@
# 底层事件处理
-----
* 在java.awt学习的时候将监听器绑定到事件源上当指定事件发生时监听器会自动匹配到相应的动作执行相应的处理方式。但在底层事件处理过程中不许要监听器能够直接获取当前发生的底层事件然后进行匹配处理。

View File

@@ -0,0 +1,14 @@
# 多线程共享受限资源
----
## &gt;多线程共享受限资源存在的问题
----
* **这个描述???**
当你坐在桌子旁边时,手里有有一把叉子,准备插起盘子里最后一块十五,当叉子碰到十五的时候,它忽然消失了。
* **解决方法**
给这个资源加锁,每个线程访问这个资源时上锁,访问结束后开锁。

View File

@@ -0,0 +1,40 @@
# 多线程的应用
------
## 多线程停止线程
----
* stop方法已经过时不能使用只能当run方法结束时才能终止线程。开启多线程程运行时代码通常是循环结构只要控制住线程通常可以让run方法结束。
* 应当设计可以修改的无限循环标志。跳出无限循环,则会终止线程。
* 当线程在循环内进入等待状态时及时线程的循环条件不满足必须终止线程但是无法执行到判断语句进行线程的终止此时必须使用interrupt()函数来达到要求。
* interrupt将处于冻结状态的线程强制转换到运行状态。此时wait()就会跑出我们处理已久的中断异常。
* 当没有指定的方式让冻结的线程回复到运行状态时这是需要对冻结进行清除。Thread提供了interrupt方法。
## 多线程 守护线程
-----
* 守护线程就是后台线程,也是一种依赖线程
* 特点:
当前台线程结束后,后台线程会自动终止,作为依赖线程,守护线程,不用强调结束。
* 方法:
setDemon()设置某个线程为守护线程
## 多线程join方法
----
* t1.join() t1抢夺cpu执行权主线程处于冻结状态t1优先执行。相当于顺序执行两个线程。主线程碰到谁的join就会等谁执行。
* 当A线程执行到了B线程的Join方法时A线程就会等待等B线程都执行完成A才会执行。join才会临时加入线程执行。当B线程进入wait时A线程也能继续执行。
* toString 方法能够显示线程的名称,线程的优先级,线程当前的分组(线程组谁调用就是谁的线程组的)
* 所有线程包括主线程默认是5。数越大优先级越高。MAX_PRIORITY,MIN_PRIORITY,
* yield()方法,当线程读到这里是,会释放执行权。这样会使所有的线程都有平均执行的效果。
## 什么时候会使用到多线程
----
* 当程序独立运算相互之间不相关的时候,可以用多线程封装一下,提高程序执行的速度

View File

@@ -0,0 +1,166 @@
# 多线程间的通讯
-----
## 多线程通讯的定义:
----
- 多个不同的线程对共同的数据进行不同的操作。
## 多线程通讯间的安全问题
-----
* 安全问题的原因
例如当多个线程对同一个数据进行不同操作时,导致各种操作的先后顺序出现混乱。
* 安全问题的解决方式
对这些线程操作数据的部分进行同步处理,使用相同的锁,将不同的部分锁起。
## 线程间通讯等待唤醒机制
-----
* 可以模仿锁的工作原理(设置标志位,记录当前是够线程占用锁内的程序,实现只能有一个线程执行锁内代码的现象)
* 步骤:
1. 设置标志位flag
2. 当标志位处于输入状态时,执行输入程序,执行完成后修改为输出状态。
3. 当标志位处于输出状态时,执行输出程序,执行完成后修改为输入状态。
## 等待唤醒机制的具体实现
----
* wait()和notify()函数必须在同步代码块或者同步函数当中使用。注意wait()会抛出中断异常。对持有监视器(锁)的线程进行操作。
* wait()和notify()的操作对象是同步中持有当前锁的线程。
* 线程的等待唤醒机制必须制定一把确定的锁。锁是任意的对象任意对象都能成为锁成为锁之后都能调用wait和notify的方法。而且这些方法都定义在Object类中。只有同一个锁上的被等待线程可以被同一个notify唤醒。等待唤醒必须是同一个锁。
## 使用新的工具类实现程序锁定和解锁
----
package painting;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* @author 宙斯
*
*/
public class LockerUsing {
/**
* @param args
*/
public static void main(String[] args) {
Resource2 r = new Resource2();
Produce2 pro = new Produce2(r);
Consumer2 con = new Consumer2(r);
Thread t1 = new Thread(pro);
Thread t2 = new Thread(con);
Thread t3 = new Thread(pro);
Thread t4 = new Thread(con);
t1.start();
t2.start();
t3.start();
t4.start();
}
}
class Resource2{
private String name;
private int count =1;
private boolean flag = false;
private Lock lock = new ReentrantLock();//新建了一个锁对象
private Condition condition_con = lock.newCondition();//生成了一个与锁相关的控制对象
private Condition condition_pro = lock.newCondition();
public void set(String name) throws InterruptedException{
lock.lock();
try{
while(flag)
condition_pro.await();
this.name= name+"..."+count++;
System.out.println(Thread.currentThread().getName()+"生产者:"+this.name);
flag = true;
condition_con.signal();
}
finally{
lock.unlock();//异常处理当中释放锁的动过一定要被执行
}
}
public void out() throws InterruptedException{
lock.lock();
try{
while(!flag)
condition_con.await();
System.out.println(Thread.currentThread().getName()+"消费者:"+this.name);
flag = false;
condition_pro.signalAll();
}
finally{
lock.unlock();
}
}
}
class Produce2 implements Runnable{
private Resource2 res;
Produce2(Resource2 res){
this.res = res;
}
public void run()
{
while(true){
try {
res.set("商品");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
class Consumer2 implements Runnable{
private Resource2 res;
Consumer2(Resource2 res){
this.res = res;
}
public void run()
{
while(true){
try {
res.out();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
* 代码的解释:
1. 单线程 -----多线程-----多线程操作同一个数据源的时候实行同步机制------带有满足条件的同步机制(睡眠唤醒机制)
2. 实现了多线程不同操作相同的程序,这个类具有模板的价值.对资源的不同操作写到资源类中并使用this资源类的锁对各种不同的操作进行上锁
3. 而非写到其他操作类中,这样能够将同步和冲突解决都封装到资源类中便于理解和操作。
4. 当线程数多于两个,比如此程序中有两个在生产两个在消费,那么标准的方式应该是通过循环判断标志位是否合格,
因为当某个线程判断满足后,但在进入之前肯能被其他线程修改标志位。
而且必须使用notifyAll()唤醒所有的线程。
5. 使用Locker及其相关类的好处
一个Locker上可以有很多condition对象执行操作也就是只唤醒对方的condition
jdk1.5实现了多线程的升级解决方案
将同步设置Synchronize替换成Lock操作可见
将Object中waitnotifynotifyAll替换成Condition对象。该对象可以Locker锁进行获取

View File

@@ -0,0 +1,48 @@
# 多线程理论补充
------
## &gt;让步机制
-----
* **yield**
thread.yield()线程执行这个函数会主动放弃执行的优先级但只是暗示别的线程能够抢到更多的资源没有确定的机制保证cpu资源一定被其他线程使用。
## &gt;休眠机制
---
* **sleep**
thread.sleep(30)线程停止执行30ms可能会跑出异常此线程调用interrupt方法中断了线程的执行。
## &gt;优先权机制
----
* **setPriority()**
thread.setPriority()通过thread类中的常量对优先级进行设定。thread.getPriority()能够获取当前线程的优先级。
## &gt;后台进程
-----
* **后台线程守护线程thread.setDaemon()**
程序运行时在后台提供的一种通用的线程当所有的非后台线程结束时后台线程守护线程自动终止。必须在线程启动之前调用方法setDaemon()将线程设置成后台线程。isDeamon判断是否为后台线程。
## &gt;加入线程
----
* **t.join(a)**
t线程此时将被挂起直到a线程结束才会被执行。当a线程结束时t.isAlive()返回为假,线程恢复。
## &gt;编码变体
-----
* **implements Runnable**
通过实现接口Runnable来达到作为线程类的方法。必须实现run方法。
* **建立有响应的用户界面**
让运算作为一个独立的线程在后台独立运行。