发表于: 2017-12-12 23:40:14

1 641


今天做的事情:


               学习一下基础中的多线程。言简意赅,多线程就是一个程序在运行时产生了不止一个线程。多线程中有进程和线程,进程是一个正在执行的程序,每一个进程执行都有一个执行顺序,也是控制单元,而线程,就是进程中的一个控制单元。

              线程和进程一样是分为五个阶段:创建,就绪,运行,堵塞,终止。


             在java中,想要实现多线程,有两种手段,一种是继续Thread类,一种是实现Runable接口。           


             并行与并发:

                                并行:多个cpu实例或者多台服务器同时执行一段处理逻辑,是真正的同时运行。

                                并发:通过cpu调度算法,让用户看起来是同时执行,实际上从cpu操作层面不是真正的同时,并发往往在场景中有共用的资源,针对这个公有的资源的瓶颈,会用TPS和QPS来反应这几个系统的处理时间。


      

               并发与并行
  • 线程安全:经常用来描绘一段代码。指在并发的情况之下,该代码经过多线程使用,线程的调度顺序不影响任何结果。这个时候使用多线程,我们只需要关注系统的内存,cpu是不是够用即可。反过来,线程不安全就意味着线程的调度顺序会影响最终结果,如不加事务的转账代码:
    void transferMoney(User from, User to, float amount){
      to.setMoney(to.getBalance() + amount);
      from.setMoney(from.getBalance() - amount);
    }
  • 同步:Java中的同步指的是通过人为的控制和调度,保证共享资源的多线程访问成为线程安全,来保证结果的准确。如上面的代码简单加入@synchronized关键字。在保证结果准确的同时,提高性能,才是优秀的程序。线程安全的优先级高于性能。

                   


                     看了这么多概念性的东西,我也快受不了了。上代码试试        

                     第一种实现方式,继承Thread

class Thread1 extends Thread {
private String name;

public Thread1(String name) {
this.name = name;
}
@Override
   public void run() {
for (int i = 0; i < 5; i++) {
System.out.println(name + "运行  :  " + i);
try {
sleep((int) Math.random() * 10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class Thread2 {

public static void main(String[] args) {
Thread1 mTh1=new Thread1("A");
Thread1 mTh2=new Thread1("B");
mTh1.start();
mTh2.start();
}

}

第一次运行:                                           

A运行  :  0                                                             
A运行  :  1                                                
A运行  :  2                                                  
A运行  :  3
B运行  :  1
A运行  :  4
B运行  :  2
B运行  :  3
B运行  :  4


第二次:
A运行  :  0
B运行  :  0
A运行  :  1
B运行  :  1
A运行  :  2
B运行  :  2
A运行  :  3
B运行  :  3
A运行  :  4
B运行  :  4


                 在程序运行main的时候,java虚拟机启动一个进程,主线程main在main()调用时候被创建,随着调用MitiSay的两个队象的start方法,另外两个线程也启动了,这样,整个应用就在多线程下运行。


                 注意:start()方法的调用并不是立即执行多线程代码,而是使得该线程为可运行的Runnable,什么时候运行时操作系统决定的。从运行结果来看,多线程是乱序执行的,因此,乱序执行的代码才有必要设计为多线程。

                 Thread.sleep()方法调用目的是不让当前线程独自霸占该进程所获取的CPU资源,以留出一定时间给其他线程执行的机会。实际上所有的多线程代码执行顺序都是不确定的,每次执行结果都是随机的。

    

            

                第二种方式: 实现Runnable

class Thread4 implements Runnable{
private String name;
public Thread4(String name) {
this.name=name;
}
@Override
   public void run() {
for (int i = 0; i < 5; i++) {
System.out.println(name + "运行  :  " + i);
try {
Thread.sleep((int) Math.random() * 10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

public class Thread3 {
public static void main(String[] args) {
new Thread(new Thread4("C")).start();
new Thread(new Thread4("D")).start();
}

}
                 通过实现Runnable接口,使得该类有了多线程的特征,run方法是一个多线程的约定,所有的多线程代码都在run方法里面,Thread类实际上也是实现Runnable接口


                 在启动多线程时,需要先通过Thread类的构造方法 Thread(Runnable target) 构造出对象,然后调用Thread对象的start()方法来运行多线程代码。 实际上所有多线程代码都是通过运行Thread的start()方法来运行的。所以,虽然实现方式不同,一个继承Thread,一个实现Runnable,同样需要复写run方法,start来启动。

         

总结:

实现Runnable接口比继承Thread类所具有的优势:   

1):适合多个相同的程序代码的线程去处理同一个资源  

2):可以避免java中的单继承的限制     

3):增加程序的健壮性,代码可以被多个线程共享,代码和数据独立  



                  跑完代码,再来看图解:


                    
1、新建状态(New):新创建了一个线程对象。
2、就绪状态(Runnable):线程对象创建后,其他线程调用了该对象的start()方法。该状态的线程位于可运行线程池中,变得可运行,等待获取CPU的使用权。
3、运行状态(Running):就绪状态的线程获取了CPU,执行程序代码。
4、阻塞状态(Blocked):阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。阻塞的情况分三种:
(一)、等待阻塞:运行的线程执行wait()方法,JVM会把该线程放入等待池中。
(二)、同步阻塞:运行的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入锁池中。
(三)、其他阻塞:运行的线程执行sleep()或join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。
5、死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期。



              关于多线程,学习到这里,博客链接:http://www.mamicode.com/info-detail-517008.html



               关于mysql优化的东西:

            

1.对查询进行优化,要尽量避免全表扫描,首先考虑在where和order by 涉及的列上建立索引。

2.应尽量避免在where子句对字段进行null值判断,否则将导致引擎放弃使用索引,而进行全表扫描。

如: select id from t where num is null;
               最好不要给数据库留Null,尽可能使用NOT NULL填充数据库。
               备注描述评论之类的可以设置为null,其他的,尽量不要
数据库char类型,字段建立时,空间固定了,不管是否插入值,都是这么大空间。如果是varchar这样的变成字段,null不占用空间。
       
3.尽量避免在where子句中使用!=和<>操作符,否则搜索引擎放弃使用索引而进行全局扫描。
4.避免在where子句中使用or来连接条件,如果一个字段有索引,一个字段没有,那么将导致引擎放弃使用索引而进行全局扫描。
    如: select id from t where num=10 or name ='admin'
    可以换成这样:select id from t where num =10  union all  select id from t where name ='admin'

5.in 和 not in 也要慎用,否则也将导致全表扫描 如: select id from t where num in (1,2,3)
   对于连续的数值,能用between就不要用in了、 如:select id from t where num between 1 and 3
   很多时候用exists代替in 是一个好的选择:
       如 反面:select num from a where num in (select num from b)
       替换: select num from a where exists ( select 1 from b where num = a.num)



                        今天还总结了一下,自己所学的东西,准备做PPT,还有欠缺的东西,基础等等。



遇到的问题:


                 无



收获:


             在很久之前已经做过多线程例子,没经常用就忘了,这次再拾起来,看了看关于sql优化和mysql优化,复习以前学习的东西。



               


返回列表 返回列表
评论

    分享到