------- android培训、java培训、期待与您交流! ----------
1:多线程
(1)线程:线程是进行的执行单元,执行路径。
进程:就是正在运行的程序。一块正在被使用的内存区域。
如果一个应用程序的执行只有一条执行路径,被称为单线程程序。
如果一个应用程序的执行有多条执行路径,被称为多线程程序。
举例:
迅雷下载,360管理界面,班长请吃饭,去医院体检
(2)JVM的启动是多线程的吗?
是。因为如果JVM启动只启动了main线程的话,那么,在程序的执行过程中,
有可能会引发内存溢出,而java很少看到这种情况,为什么呢,就是因为,
java的垃圾回收线程一直也在运行,当内存不够的情况,会自动去扫描内存中
是否有垃圾存在,有就立马清除。
这样来说,最低有两个线程启动了。所以,JVM的启动是多线程的。
(3)自己如何模拟多线程程序
A:继承Thread类
步骤:
a:创建一个类,继承Thread类
b:重写run方法
c:创建类对象,调用start方法
代码体现:
public class ThreadDemo extends Thread
{
@Override
public void run()
{
for(int x=0; x<100; x++)
{
System.out.println(getName()+"***"+x);
}
}
}
public class ThreadDemoTest
{
public static void main(String[] args)
{
ThreadDemo td1 = new ThreadDemo("刘备");
ThreadDemo td2 = new ThreadDemo("孙权");
td1.start();
td2.start();
}
}
B:实现Runnable接口
步骤:
a:创建一个类,实现Runnable接口
b:重写run方法
c:创建Thread类对象,创建Runnable子类对象,把Runnable的子类
对象作为构造参数传递给Thread的构造方法
d:调用start方法
代码体现:
public class RunnableDemo implements Runnable
{
@Override
public void run()
{
for(int x=0; x<100; x++)
{
System.out.println(Thread.currentThread().getName()+"***"+x);
}
}
}
public class ThreadDemoTest
{
public static void main(String[] args)
{
RunnableDemo rd = new RunnableDemo();
Thread td1 = new Thread(rd,"林青霞");
Thread td2 = new Thread(rd,"刘意");
td1.start();
td2.start();
}
}
(4)实现多线程的方式有几种,分别怎么实现?
(5)启动线程调用的是哪个方法,它做了什么事情?
启动线程调用的是start()方法。
它启动线程,并且自动调用了run()方法。
start()和run()的区别?
(6)线程的生命周期及每个状态的特点。
新建:创建线程对象
就绪:具有执行资格,没有执行权
运行:具有执行资格,有执行权
阻塞:没有执行资格,没有执行权
死亡:对象变成垃圾
内存体现:
(7)下午通过卖票程序演示出线程安全问题。
A:线程安全是怎么产生的?
线程的随机性
线程的延迟性
B:如何判断某段代码有没有线程安全问题呢?
a:有没有共享数据
b:看是否有多条语句操作共享数据
c:看是否有多个线程进行操作
c:如何解决线程安全问题?
a:同步代码块
synchronized(对象)
{
需要被同步的代码。
}
对象:可以是任意对象。
b:同步方法
在方法上添加synchronized关键字即可
锁对象:this
注意:静态方法的锁对象 当前类的字节码文件对象。
类名.class
D:同步前提
a:两个以上的线程操作的时候
b:对这多个线程加同步必须使用的是同一把锁
E:同步弊端
每次程序的执行都会去判断锁对象,消耗了资源,降低了效率。
线程安全,效率低。
线程不安全,效率高。
开发中的一个难题:要么效率,要么安全。
(8)卖票程序
public class Ticket implements Runnable
{
//定义100张票
private int tickets = 100;
@Override
public void run()
{
while(true)
{
synchronized(this){
if(tickets>0)
{
try{
Thread.sleep(10);
}catch(InterruptedException e){
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"正在卖出第"+(tickets--)+"张票");
}
}
}
}
}
public class Test
{
public static void main(String[] args)
{
Ticket t = new Ticket();
Thread t1 = new Thread(t,"窗口1");
Thread t2 = new Thread(t,"窗口2");
Thread t3 = new Thread(t,"窗口3");
Thread t4 = new Thread(t,"窗口4");
t1.start();
t2.start();
t3.start();
t4.start();
}
}
(9)单例设计模式的懒汉式,请问他有没有线程安全问题
public class Student
{
private Student(){}
private static Student s = null;
public synchronized static Student getStudent()
{
//t1,t2,t3
if(s==null)
{
//t1,t2,t3
s = new Student();
//t1线程首先创建了一个对象
//t2线程继续创建了一个对象
//t3线程又创建了一个对象
}
return s;
}
}
A:延迟加载
B:线程安全问题
//开发中,用饿汉式即可。
public class Student
{
private Student(){}
private static Student s = new Student();
public static Student getStudent()
{
return s;
}
}
线程范围内的共享数据:在同一个线程数据共享,但在不同线程,数据不共享。
代码体现:
private static int date = 0;//共享数据
public static void main(String[] args) {
for( int i=0;i<=1;i++){
new Thread(new Runnable(){
@Override
public void run() {
date = new Random().nextInt();
System.out.println("***"+Thread.currentThread().getName()+"***"+date);
new A().get();
new B().get();
}
}).start();
}
}
static class A{
public void get(){
System.out.println("A***"+Thread.currentThread().getName()+"***"+date);
}
}
static class B{
public void get(){
System.out.println("B***"+Thread.currentThread().getName()+"***"+date);
}
}
}