---------------------- <a href="http://edu.csdn.net"target="blank">ASP.Net+Android+IOS开发</a>、<a href="http://edu.csdn.net"target="blank">.Net培训</a>、期待与您交流! ----------------------
进程:是一个正在执行中的程序。
每一个进程执行都有一个执行顺序。该顺序是一个执行路径,或者叫一个控制单元。
线程:就是进程中的一个独立的控制单元。
线程在控制着进程的执行。
一个进程中至少有一个线程。
有两种方案。
方案1:继承自Thread类。
步骤:
A:自定义类继承Thread类。
B:在自定义类中重写run方法。
C:创建自定义类对象。
D:启动线程。
public class MyThread extends Thread {
@Override
public void run() {
for(int x=0; x<100; x++){
System.out.println(getName()+"***"+x);
}
}
}
public class MyThreadTest {
public static void main(String[] args) {
// Thread mt = new MyThread();
MyThread mt1 = new MyThread();
MyThread mt2 = new MyThread();
mt1.setName("1");
mt2.setName(2");
mt1.start();
mt2.start();
}
}
方案2:实现Runnable接口。
A:自定义类实现Runnable接口。
B:重写run()方法。
C:创建自定义类对象。
D:创建线程对象,把自定义类对象的作为构造参数传递。
E:启动线程对象。
方案2:实现Runnable接口。
A:自定义类实现Runnable接口。
B:重写run()方法。
C:创建自定义类对象。
D:创建线程对象,把自定义类对象的作为构造参数传递。
E:启动线程对象。
public class MyThread implements Runnable {
@Override
public void run() {
for (int x = 0; x < 100; x++) {
System.out.println(Thread.currentThread().getName() + "***" + x);
}
}
public class MyThreadTest {
public static void main(String[] args) {
MyThread my = new MyThread();
Thread t1 = new Thread(my);
Thread t2 = new Thread(my);
t1.setName("1");
t2.setName("2");
t1.start();
t2.start();
}
线程安全问题:
注意原因:线程的随机性和延迟性。
如何判断是否有线程安全问题:
A:是否有共享数据
B:共享数据是否被多条语句操作
C:是否有多个线程在执行
解决线程安全问题:
A:同步代码块
synchronized(锁对象)
{
被同步的代码;
}
锁对象是任意对象。
B:同步方法
在方法上加同步关键字。
锁对象是this。
注意:静态同步方法的锁对象是
当前类名.class
--
当前类的字节码文件对象
同步的前提:
1,必须要有两个或者两个以上的线程。
2,必须是多个线程使用同一个锁。
必须保证同步中只能有一个线程在运行。
好处:解决了多线程的安全问题。
弊端:多个线程需要判断锁,较为消耗资源,
卖票案例用同步解决。
public class Tickets implements Runnable
{
private int tickets = 100;
private Object obj = new Object();
@Override
public void run()
{
while(true)
{
synchronized(obj)
{
if(tickets>0)
{
System.out.println(Thread.currentThread().getName()+"正在售出"+(tickets--)+"张票");
}
}
}
}
}
public class Test
{
public static void main(String[] args)
{
Tickets t = new Tickets();
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();
}
}
数需要被对象调用。那么函数都有一个所属对象引用。就是this。
所以同步函数使用的锁是this。
静态进内存是,内存中没有本类对象,但是一定有该类对应的字节码文件对象。
类名.class 该对象的类型是Class
静态的同步方法,使用的锁是该方法所在类的字节码文件对象。 类名.class
/*
单例设计模式。
/
//饿汉式。
/*
class Single
{
private static final Single s = new Single();
private Single(){}
public static Single getInstance()
{
return s;
}
}
*/
延迟加载!
//懒汉式
class Single
{
private static Single s = null;
private Single(){}
public static Single getInstance()
{
if(s==null)
{
synchronized(Single.class)
{
if(s==null)
//--->A;
s = new Single();
}
}
return s;
}
}
死锁。
同步中嵌套同步。
class Test implements Runnable
{
private boolean flag;
Test(boolean flag)
{
this.flag = flag;
}
public void run()
{
if(flag)
{
while(true)
{
synchronized(MyLock.locka)
{
System.out.println(Thread.currentThread().getName()+"...if locka ");
synchronized(MyLock.lockb)
{
System.out.println(Thread.currentThread().getName()+"..if lockb");
}
}
}
}
else
{
while(true)
{
synchronized(MyLock.lockb)
{
System.out.println(Thread.currentThread().getName()+"..else lockb");
synchronized(MyLock.locka)
{
System.out.println(Thread.currentThread().getName()+".....else locka");
}
}
}
}
}
}
class MyLock
{
static Object locka = new Object();
static Object lockb = new Object();
}
class DeadLockTest
{
public static void main(String[] args)
{
Thread t1 = new Thread(new Test(true));
Thread t2 = new Thread(new Test(false));
t1.start();
t2.start();
有两种方案。
方案1:继承自Thread类。
步骤:
A:自定义类继承Thread类。
B:在自定义类中重写run方法。
C:创建自定义类对象。
D:启动线程。
public class MyThread extends Thread {
@Override
public void run() {
for(int x=0; x<100; x++){
System.out.println(getName()+"***"+x);
}
}
}
public class MyThreadTest {
public static void main(String[] args) {
// Thread mt = new MyThread();
MyThread mt1 = new MyThread();
MyThread mt2 = new MyThread();
mt1.setName("1");
mt2.setName(2");
mt1.start();
mt2.start();
}
}
方案2:实现Runnable接口。
A:自定义类实现Runnable接口。
B:重写run()方法。
C:创建自定义类对象。
D:创建线程对象,把自定义类对象的作为构造参数传递。
E:启动线程对象。
方案2:实现Runnable接口。
A:自定义类实现Runnable接口。
B:重写run()方法。
C:创建自定义类对象。
D:创建线程对象,把自定义类对象的作为构造参数传递。
E:启动线程对象。
public class MyThread implements Runnable {
@Override
public void run() {
for (int x = 0; x < 100; x++) {
System.out.println(Thread.currentThread().getName() + "***" + x);
}
}
public class MyThreadTest {
public static void main(String[] args) {
MyThread my = new MyThread();
Thread t1 = new Thread(my);
Thread t2 = new Thread(my);
t1.setName("1");
t2.setName("2");
t1.start();
t2.start();
}
线程安全问题:
注意原因:线程的随机性和延迟性。
如何判断是否有线程安全问题:
A:是否有共享数据
B:共享数据是否被多条语句操作
C:是否有多个线程在执行
解决线程安全问题:
A:同步代码块
synchronized(锁对象)
{
被同步的代码;
}
锁对象是任意对象。
B:同步方法
在方法上加同步关键字。
锁对象是this。
注意:静态同步方法的锁对象是
当前类名.class
--
当前类的字节码文件对象
同步的前提:
1,必须要有两个或者两个以上的线程。
2,必须是多个线程使用同一个锁。
必须保证同步中只能有一个线程在运行。
好处:解决了多线程的安全问题。
弊端:多个线程需要判断锁,较为消耗资源,
卖票案例用同步解决。
public class Tickets implements Runnable
{
private int tickets = 100;
private Object obj = new Object();
@Override
public void run()
{
while(true)
{
synchronized(obj)
{
if(tickets>0)
{
System.out.println(Thread.currentThread().getName()+"正在售出"+(tickets--)+"张票");
}
}
}
}
}
public class Test
{
public static void main(String[] args)
{
Tickets t = new Tickets();
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();
}
}
数需要被对象调用。那么函数都有一个所属对象引用。就是this。
所以同步函数使用的锁是this。
静态进内存是,内存中没有本类对象,但是一定有该类对应的字节码文件对象。
类名.class 该对象的类型是Class
静态的同步方法,使用的锁是该方法所在类的字节码文件对象。 类名.class
/*
单例设计模式。
/
//饿汉式。
/*
class Single
{
private static final Single s = new Single();
private Single(){}
public static Single getInstance()
{
return s;
}
}
*/
延迟加载!
//懒汉式
class Single
{
private static Single s = null;
private Single(){}
public static Single getInstance()
{
if(s==null)
{
synchronized(Single.class)
{
if(s==null)
//--->A;
s = new Single();
}
}
return s;
}
}
死锁。
同步中嵌套同步。
class Test implements Runnable
{
private boolean flag;
Test(boolean flag)
{
this.flag = flag;
}
public void run()
{
if(flag)
{
while(true)
{
synchronized(MyLock.locka)
{
System.out.println(Thread.currentThread().getName()+"...if locka ");
synchronized(MyLock.lockb)
{
System.out.println(Thread.currentThread().getName()+"..if lockb");
}
}
}
}
else
{
while(true)
{
synchronized(MyLock.lockb)
{
System.out.println(Thread.currentThread().getName()+"..else lockb");
synchronized(MyLock.locka)
{
System.out.println(Thread.currentThread().getName()+".....else locka");
}
}
}
}
}
}
class MyLock
{
static Object locka = new Object();
static Object lockb = new Object();
}
class DeadLockTest
{
public static void main(String[] args)
{
Thread t1 = new Thread(new Test(true));
Thread t2 = new Thread(new Test(false));
t1.start();
t2.start();
线程间通讯:
其实就是多个线程在操作同一个资源,
但是操作的动作不同。
wait:
notify();
notifyAll();
都使用在同步中,因为要对持有监视器(锁)的线程操作。
所以要使用在同步中,因为只有同步才具有锁。
为什么这些操作线程的方法要定义Object类中呢?
因为这些方法在操作同步中线程时,都必须要标识它们所操作线程只有的锁,
只有同一个锁上的被等待线程,可以被同一个锁上notify唤醒。
不可以对不同锁中的线程进行唤醒。
也就是说,等待和唤醒必须是同一个锁。
而锁可以是任意对象,所以可以被任意对象调用的方法定义Object类中。
---------------------- <a href="http://edu.csdn.net"target="blank">ASP.Net+Android+IOS开发</a>、<a href="http://edu.csdn.net"target="blank">.Net培训</a>、期待与您交流! ----------------------
线程间通讯:
其实就是多个线程在操作同一个资源,
但是操作的动作不同。
wait:
notify();
notifyAll();
都使用在同步中,因为要对持有监视器(锁)的线程操作。
所以要使用在同步中,因为只有同步才具有锁。
为什么这些操作线程的方法要定义Object类中呢?
因为这些方法在操作同步中线程时,都必须要标识它们所操作线程只有的锁,
只有同一个锁上的被等待线程,可以被同一个锁上notify唤醒。
不可以对不同锁中的线程进行唤醒。
也就是说,等待和唤醒必须是同一个锁。
而锁可以是任意对象,所以可以被任意对象调用的方法定义Object类中。