线程
我理解的是:从main方法进线程栈到所有的方法执行出来,然后main方法出栈,一条线的执行完成,叫线程;
线程栈与栈帧的关系
线程栈里面的方法都是拷贝过来的称为栈帧;每一个方法都是帧;
关于类锁和对象锁
假如有两个方法,在其中一个方法上加上锁(synchronized),这两个方法就不会锁上;
如果是两个静态方法,在方法前加上锁,就会一起锁上,先执行第一个方法,然后执行第二个方法;这个就是类锁;
如果是两个非静态的方法,那么在方法前加上锁,就会一起锁上,先执行第一个方法,然后执行第二个方法;这个就是对象锁;
也就是说,静态的方法加锁互相锁上,非静态的互相锁上;
注意:能够互相锁上的方法必须指向同一个内存区域,只有产生占用时用锁才能提升效率
ps:(静态方法和非静态方法的区别:在public中有static的是静态方法,没有的是非静态方法)
多线程
当产生CPU浪费时,为了提升效率,可以用多线程,用多个线程互相一起执行,为了防止产生堵塞,在方法里面加入锁,用来控制方法的执行;
以上就是我对这些概念的简单理解
下面我写一个关于多线程的简单的卖票程序;
首先我们写线程里面的东西;
public class ThreadTest extends Thread{//这里继承于java的Thread类 private DataTest data;//线程内部的对象 private String name; ThreadTest(DataTest data,String name){ this.data = data; this.name = name; } public void run() {//run方法是线程里面的特殊方法,一开始先执行run方法 FlagTest f = new FlagTest(); while( f.flag == 0) {//设定一个因素,可以开始run方法 data.method3(name,f); } } }
我们新建一个类,然后写一个条件,为了让run方法顺利执行
public class FlagTest { public int flag = 0; }
下面我们开始写线程
public static void main(String[] args) { // TODO Auto-generated method stub DataTest test = new DataTest(); ThreadTest t1 = new ThreadTest(test,"窗口1"); ThreadTest t2 = new ThreadTest(test,"窗口2"); ThreadTest t3 = new ThreadTest(test,"窗口3"); t1.start(); t2.start(); t3.start(); }
我们创建了三个线程
下面我们写线程里面改运行的方法,这里我写了一个关卖票的方法,建议放在一个新的类里面
private static int ticket = 10000;//因为有锁的关系,所以定义了一个静态的数值,代表票的数量 public synchronized void method3(String name,FlagTest f) { if( ticket == 0) {//如果买完了 f.flag = 1;//flag变化,run方法没办法用了,线程结束 System.out.println("票卖完毕了"); return; } System.out.println(name + "卖出了第" + ticket); ticket = ticket - 1; }
当我们写线程的时候,一个方法里面最好包含了读和写,因为读和写放在两个方法里会产生线程安全的问题;
就这一个锁,可能看不出来锁的是什么,列举一个例子:
//我们假设我们想调用树里面的数值去运算 public synchronized void run() { while(tree.value<10) { tree.value++; } }
方法里面加了锁,那么锁的是什么呢,锁的是tree,把树给锁上了
我们想要锁上树里面的数值应该怎样写呢?
public synchronized void run() { while(tree.value<10) { tree.yunshuan();//这里我们是把树给锁上了,包括里面的运算方法 } }
然后在树里面写一个yunshuan的方法
// 正确锁上锁内部引用资源 public synchronized void yunshuan() { value=value+1; }
这样就可以把树里面的东西给锁上了;
其实总结一下线程,我认为,线程里面一开始都有一个run方法,在开始线程的时候,先把需要用到拷贝一份,然后去执行;
如果是多线程,会存在可能拷贝不一样的,跟上一个不一样,在并发高的地方更容易产生不一样的线程;
线程拷贝只能拷贝栈里面的数据,堆里面的不能拷贝,在进行线程栈的时候,和顺序相关的进入栈里面,跟顺序无关的进入堆里面,变量栈里面存的是堆里面的地址,在堆里面运行,当发生了多个线程同时调用同一个地址时,会发生堵塞,这时候加锁,使其顺序运行,大大提升了效率,减少堵塞的情况;这就是线程和锁的关系;
对于线程和锁的理解还是比较浅的,而且大晚上了,可能有些错误,希望路过的各位大佬给一些建议,我会时时改进,祝大家新年快乐,